You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2014/09/05 00:35:40 UTC

[01/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Repository: ambari
Updated Branches:
  refs/heads/branch-alerts-dev 0de98b020 -> 91ae5f27e


http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py
new file mode 100644
index 0000000..008a0a9
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.lexnparse
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    All the unittests regarding lexing, parsing and syntax.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import time
+import tempfile
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, Template, TemplateSyntaxError, \
+     UndefinedError, nodes
+
+env = Environment()
+
+
+# how does a string look like in jinja syntax?
+if sys.version_info < (3, 0):
+    def jinja_string_repr(string):
+        return repr(string)[1:]
+else:
+    jinja_string_repr = repr
+
+
+class LexerTestCase(JinjaTestCase):
+
+    def test_raw1(self):
+        tmpl = env.from_string('{% raw %}foo{% endraw %}|'
+                               '{%raw%}{{ bar }}|{% baz %}{%       endraw    %}')
+        assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
+
+    def test_raw2(self):
+        tmpl = env.from_string('1  {%- raw -%}   2   {%- endraw -%}   3')
+        assert tmpl.render() == '123'
+
+    def test_balancing(self):
+        env = Environment('{%', '%}', '${', '}')
+        tmpl = env.from_string('''{% for item in seq
+            %}${{'foo': item}|upper}{% endfor %}''')
+        assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
+
+    def test_comments(self):
+        env = Environment('<!--', '-->', '{', '}')
+        tmpl = env.from_string('''\
+<ul>
+<!--- for item in seq -->
+  <li>{item}</li>
+<!--- endfor -->
+</ul>''')
+        assert tmpl.render(seq=range(3)) == ("<ul>\n  <li>0</li>\n  "
+                                             "<li>1</li>\n  <li>2</li>\n</ul>")
+
+    def test_string_escapes(self):
+        for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
+            tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
+            assert tmpl.render() == char
+        assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
+
+    def test_bytefallback(self):
+        from pprint import pformat
+        tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
+        assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
+
+    def test_operators(self):
+        from jinja2.lexer import operators
+        for test, expect in operators.iteritems():
+            if test in '([{}])':
+                continue
+            stream = env.lexer.tokenize('{{ %s }}' % test)
+            stream.next()
+            assert stream.current.type == expect
+
+    def test_normalizing(self):
+        for seq in '\r', '\r\n', '\n':
+            env = Environment(newline_sequence=seq)
+            tmpl = env.from_string('1\n2\r\n3\n4\n')
+            result = tmpl.render()
+            assert result.replace(seq, 'X') == '1X2X3X4'
+
+
+class ParserTestCase(JinjaTestCase):
+
+    def test_php_syntax(self):
+        env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
+        tmpl = env.from_string('''\
+<!-- I'm a comment, I'm not interesting -->\
+<? for item in seq -?>
+    <?= item ?>
+<?- endfor ?>''')
+        assert tmpl.render(seq=range(5)) == '01234'
+
+    def test_erb_syntax(self):
+        env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
+        tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>\
+<% for item in seq -%>
+    <%= item %>
+<%- endfor %>''')
+        assert tmpl.render(seq=range(5)) == '01234'
+
+    def test_comment_syntax(self):
+        env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
+        tmpl = env.from_string('''\
+<!--# I'm a comment, I'm not interesting -->\
+<!-- for item in seq --->
+    ${item}
+<!--- endfor -->''')
+        assert tmpl.render(seq=range(5)) == '01234'
+
+    def test_balancing(self):
+        tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
+        assert tmpl.render() == 'bar'
+
+    def test_start_comment(self):
+        tmpl = env.from_string('''{# foo comment
+and bar comment #}
+{% macro blub() %}foo{% endmacro %}
+{{ blub() }}''')
+        assert tmpl.render().strip() == 'foo'
+
+    def test_line_syntax(self):
+        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
+        tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+    ${item}
+% endfor''')
+        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
+               range(5)
+
+        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
+        tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+    ${item} ## the rest of the stuff
+% endfor''')
+        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
+                range(5)
+
+    def test_line_syntax_priority(self):
+        # XXX: why is the whitespace there in front of the newline?
+        env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
+        tmpl = env.from_string('''\
+/* ignore me.
+   I'm a multiline comment */
+## for item in seq:
+* ${item}          # this is just extra stuff
+## endfor''')
+        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2'
+        env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##')
+        tmpl = env.from_string('''\
+/* ignore me.
+   I'm a multiline comment */
+# for item in seq:
+* ${item}          ## this is just extra stuff
+    ## extra stuff i just want to ignore
+# endfor''')
+        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
+
+    def test_error_messages(self):
+        def assert_error(code, expected):
+            try:
+                Template(code)
+            except TemplateSyntaxError, e:
+                assert str(e) == expected, 'unexpected error message'
+            else:
+                assert False, 'that was suposed to be an error'
+
+        assert_error('{% for item in seq %}...{% endif %}',
+                     "Encountered unknown tag 'endif'. Jinja was looking "
+                     "for the following tags: 'endfor' or 'else'. The "
+                     "innermost block that needs to be closed is 'for'.")
+        assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
+                     "Encountered unknown tag 'endfor'. Jinja was looking for "
+                     "the following tags: 'elif' or 'else' or 'endif'. The "
+                     "innermost block that needs to be closed is 'if'.")
+        assert_error('{% if foo %}',
+                     "Unexpected end of template. Jinja was looking for the "
+                     "following tags: 'elif' or 'else' or 'endif'. The "
+                     "innermost block that needs to be closed is 'if'.")
+        assert_error('{% for item in seq %}',
+                     "Unexpected end of template. Jinja was looking for the "
+                     "following tags: 'endfor' or 'else'. The innermost block "
+                     "that needs to be closed is 'for'.")
+        assert_error('{% block foo-bar-baz %}',
+                     "Block names in Jinja have to be valid Python identifiers "
+                     "and may not contain hypens, use an underscore instead.")
+        assert_error('{% unknown_tag %}',
+                     "Encountered unknown tag 'unknown_tag'.")
+
+
+class SyntaxTestCase(JinjaTestCase):
+
+    def test_call(self):
+        env = Environment()
+        env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
+        tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
+        assert tmpl.render() == 'abdfh'
+
+    def test_slicing(self):
+        tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
+        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+    def test_attr(self):
+        tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
+        assert tmpl.render(foo={'bar': 42}) == '42|42'
+
+    def test_subscript(self):
+        tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
+        assert tmpl.render(foo=[0, 1, 2]) == '0|2'
+
+    def test_tuple(self):
+        tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
+        assert tmpl.render() == '()|(1,)|(1, 2)'
+
+    def test_math(self):
+        tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
+        assert tmpl.render() == '1.5|8'
+
+    def test_div(self):
+        tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
+        assert tmpl.render() == '1|1.5|1'
+
+    def test_unary(self):
+        tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
+        assert tmpl.render() == '3|-3'
+
+    def test_concat(self):
+        tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
+        assert tmpl.render() == '[1, 2]foo'
+
+    def test_compare(self):
+        tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
+                               '{{ 2 == 2 }}|{{ 1 <= 1 }}')
+        assert tmpl.render() == 'True|True|True|True|True'
+
+    def test_inop(self):
+        tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
+        assert tmpl.render() == 'True|False'
+
+    def test_literals(self):
+        tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
+        assert tmpl.render().lower() == '[]|{}|()'
+
+    def test_bool(self):
+        tmpl = env.from_string('{{ true and false }}|{{ false '
+                               'or true }}|{{ not false }}')
+        assert tmpl.render() == 'False|True|True'
+
+    def test_grouping(self):
+        tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
+        assert tmpl.render() == 'False'
+
+    def test_django_attr(self):
+        tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
+        assert tmpl.render() == '1|1'
+
+    def test_conditional_expression(self):
+        tmpl = env.from_string('''{{ 0 if true else 1 }}''')
+        assert tmpl.render() == '0'
+
+    def test_short_conditional_expression(self):
+        tmpl = env.from_string('<{{ 1 if false }}>')
+        assert tmpl.render() == '<>'
+
+        tmpl = env.from_string('<{{ (1 if false).bar }}>')
+        self.assert_raises(UndefinedError, tmpl.render)
+
+    def test_filter_priority(self):
+        tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
+        assert tmpl.render() == 'FOOBAR'
+
+    def test_function_calls(self):
+        tests = [
+            (True, '*foo, bar'),
+            (True, '*foo, *bar'),
+            (True, '*foo, bar=42'),
+            (True, '**foo, *bar'),
+            (True, '**foo, bar'),
+            (False, 'foo, bar'),
+            (False, 'foo, bar=42'),
+            (False, 'foo, bar=23, *args'),
+            (False, 'a, b=c, *d, **e'),
+            (False, '*foo, **bar')
+        ]
+        for should_fail, sig in tests:
+            if should_fail:
+                self.assert_raises(TemplateSyntaxError,
+                    env.from_string, '{{ foo(%s) }}' % sig)
+            else:
+                env.from_string('foo(%s)' % sig)
+
+    def test_tuple_expr(self):
+        for tmpl in [
+            '{{ () }}',
+            '{{ (1, 2) }}',
+            '{{ (1, 2,) }}',
+            '{{ 1, }}',
+            '{{ 1, 2 }}',
+            '{% for foo, bar in seq %}...{% endfor %}',
+            '{% for x in foo, bar %}...{% endfor %}',
+            '{% for x in foo, %}...{% endfor %}'
+        ]:
+            assert env.from_string(tmpl)
+
+    def test_trailing_comma(self):
+        tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
+        assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
+
+    def test_block_end_name(self):
+        env.from_string('{% block foo %}...{% endblock foo %}')
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '{% block x %}{% endblock y %}')
+
+    def test_contant_casing(self):
+        for const in True, False, None:
+            tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
+                str(const), str(const).lower(), str(const).upper()
+            ))
+            assert tmpl.render() == '%s|%s|' % (const, const)
+
+    def test_test_chaining(self):
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '{{ foo is string is sequence }}')
+        env.from_string('{{ 42 is string or 42 is number }}'
+            ).render() == 'True'
+
+    def test_string_concatenation(self):
+        tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
+        assert tmpl.render() == 'foobarbaz'
+
+    def test_notin(self):
+        bar = xrange(100)
+        tmpl = env.from_string('''{{ not 42 in bar }}''')
+        assert tmpl.render(bar=bar) == unicode(not 42 in bar)
+
+    def test_implicit_subscribed_tuple(self):
+        class Foo(object):
+            def __getitem__(self, x):
+                return x
+        t = env.from_string('{{ foo[1, 2] }}')
+        assert t.render(foo=Foo()) == u'(1, 2)'
+
+    def test_raw2(self):
+        tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
+        assert tmpl.render() == '{{ FOO }} and {% BAR %}'
+
+    def test_const(self):
+        tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
+                               '{{ none is defined }}|{{ missing is defined }}')
+        assert tmpl.render() == 'True|False|None|True|False'
+
+    def test_neg_filter_priority(self):
+        node = env.parse('{{ -1|foo }}')
+        assert isinstance(node.body[0].nodes[0], nodes.Filter)
+        assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
+
+    def test_const_assign(self):
+        constass1 = '''{% set true = 42 %}'''
+        constass2 = '''{% for none in seq %}{% endfor %}'''
+        for tmpl in constass1, constass2:
+            self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
+
+    def test_localset(self):
+        tmpl = env.from_string('''{% set foo = 0 %}\
+{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
+{{ foo }}''')
+        assert tmpl.render() == '0'
+
+    def test_parse_unary(self):
+        tmpl = env.from_string('{{ -foo["bar"] }}')
+        assert tmpl.render(foo={'bar': 42}) == '-42'
+        tmpl = env.from_string('{{ -foo["bar"]|abs }}')
+        assert tmpl.render(foo={'bar': 42}) == '42'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(LexerTestCase))
+    suite.addTest(unittest.makeSuite(ParserTestCase))
+    suite.addTest(unittest.makeSuite(SyntaxTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py
new file mode 100644
index 0000000..0ff0d04
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py
@@ -0,0 +1,191 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.loader
+    ~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test the loaders.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import time
+import tempfile
+import shutil
+import unittest
+
+from jinja2.testsuite import JinjaTestCase, dict_loader, \
+     package_loader, filesystem_loader, function_loader, \
+     choice_loader, prefix_loader
+
+from jinja2 import Environment, loaders
+from jinja2.loaders import split_template_path
+from jinja2.exceptions import TemplateNotFound
+
+
+class LoaderTestCase(JinjaTestCase):
+
+    def test_dict_loader(self):
+        env = Environment(loader=dict_loader)
+        tmpl = env.get_template('justdict.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_package_loader(self):
+        env = Environment(loader=package_loader)
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_filesystem_loader(self):
+        env = Environment(loader=filesystem_loader)
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        tmpl = env.get_template('foo/test.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_choice_loader(self):
+        env = Environment(loader=choice_loader)
+        tmpl = env.get_template('justdict.html')
+        assert tmpl.render().strip() == 'FOO'
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_function_loader(self):
+        env = Environment(loader=function_loader)
+        tmpl = env.get_template('justfunction.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_prefix_loader(self):
+        env = Environment(loader=prefix_loader)
+        tmpl = env.get_template('a/test.html')
+        assert tmpl.render().strip() == 'BAR'
+        tmpl = env.get_template('b/justdict.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing')
+
+    def test_caching(self):
+        changed = False
+        class TestLoader(loaders.BaseLoader):
+            def get_source(self, environment, template):
+                return u'foo', None, lambda: not changed
+        env = Environment(loader=TestLoader(), cache_size=-1)
+        tmpl = env.get_template('template')
+        assert tmpl is env.get_template('template')
+        changed = True
+        assert tmpl is not env.get_template('template')
+        changed = False
+
+        env = Environment(loader=TestLoader(), cache_size=0)
+        assert env.get_template('template') \
+               is not env.get_template('template')
+
+        env = Environment(loader=TestLoader(), cache_size=2)
+        t1 = env.get_template('one')
+        t2 = env.get_template('two')
+        assert t2 is env.get_template('two')
+        assert t1 is env.get_template('one')
+        t3 = env.get_template('three')
+        assert 'one' in env.cache
+        assert 'two' not in env.cache
+        assert 'three' in env.cache
+
+    def test_split_template_path(self):
+        assert split_template_path('foo/bar') == ['foo', 'bar']
+        assert split_template_path('./foo/bar') == ['foo', 'bar']
+        self.assert_raises(TemplateNotFound, split_template_path, '../foo')
+
+
+class ModuleLoaderTestCase(JinjaTestCase):
+    archive = None
+
+    def compile_down(self, zip='deflated', py_compile=False):
+        super(ModuleLoaderTestCase, self).setup()
+        log = []
+        self.reg_env = Environment(loader=prefix_loader)
+        if zip is not None:
+            self.archive = tempfile.mkstemp(suffix='.zip')[1]
+        else:
+            self.archive = tempfile.mkdtemp()
+        self.reg_env.compile_templates(self.archive, zip=zip,
+                                       log_function=log.append,
+                                       py_compile=py_compile)
+        self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
+        return ''.join(log)
+
+    def teardown(self):
+        super(ModuleLoaderTestCase, self).teardown()
+        if hasattr(self, 'mod_env'):
+            if os.path.isfile(self.archive):
+                os.remove(self.archive)
+            else:
+                shutil.rmtree(self.archive)
+            self.archive = None
+
+    def test_log(self):
+        log = self.compile_down()
+        assert 'Compiled "a/foo/test.html" as ' \
+               'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
+        assert 'Finished compiling templates' in log
+        assert 'Could not compile "a/syntaxerror.html": ' \
+               'Encountered unknown tag \'endif\'' in log
+
+    def _test_common(self):
+        tmpl1 = self.reg_env.get_template('a/test.html')
+        tmpl2 = self.mod_env.get_template('a/test.html')
+        assert tmpl1.render() == tmpl2.render()
+
+        tmpl1 = self.reg_env.get_template('b/justdict.html')
+        tmpl2 = self.mod_env.get_template('b/justdict.html')
+        assert tmpl1.render() == tmpl2.render()
+
+    def test_deflated_zip_compile(self):
+        self.compile_down(zip='deflated')
+        self._test_common()
+
+    def test_stored_zip_compile(self):
+        self.compile_down(zip='stored')
+        self._test_common()
+
+    def test_filesystem_compile(self):
+        self.compile_down(zip=None)
+        self._test_common()
+
+    def test_weak_references(self):
+        self.compile_down()
+        tmpl = self.mod_env.get_template('a/test.html')
+        key = loaders.ModuleLoader.get_template_key('a/test.html')
+        name = self.mod_env.loader.module.__name__
+
+        assert hasattr(self.mod_env.loader.module, key)
+        assert name in sys.modules
+
+        # unset all, ensure the module is gone from sys.modules
+        self.mod_env = tmpl = None
+
+        try:
+            import gc
+            gc.collect()
+        except:
+            pass
+
+        assert name not in sys.modules
+
+    def test_byte_compilation(self):
+        log = self.compile_down(py_compile=True)
+        assert 'Byte-compiled "a/test.html"' in log
+        tmpl1 = self.mod_env.get_template('a/test.html')
+        mod = self.mod_env.loader.module. \
+            tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
+        assert mod.__file__.endswith('.pyc')
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(LoaderTestCase))
+    suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py
new file mode 100644
index 0000000..a39c3cb
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py
@@ -0,0 +1,258 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.regression
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests corner cases and bugs.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
+     TemplateNotFound, PrefixLoader
+
+env = Environment()
+
+
+class CornerTestCase(JinjaTestCase):
+
+    def test_assigned_scoping(self):
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) -%}
+            [{{ item }}]
+        {%- endfor %}
+        {{- item -}}
+        ''')
+        assert t.render(item=42) == '[1][2][3][4]42'
+
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) -%}
+            [{{ item }}]
+        {%- endfor %}
+        {%- set item = 42 %}
+        {{- item -}}
+        ''')
+        assert t.render() == '[1][2][3][4]42'
+
+        t = env.from_string('''
+        {%- set item = 42 %}
+        {%- for item in (1, 2, 3, 4) -%}
+            [{{ item }}]
+        {%- endfor %}
+        {{- item -}}
+        ''')
+        assert t.render() == '[1][2][3][4]42'
+
+    def test_closure_scoping(self):
+        t = env.from_string('''
+        {%- set wrapper = "<FOO>" %}
+        {%- for item in (1, 2, 3, 4) %}
+            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+            {{- wrapper() }}
+        {%- endfor %}
+        {{- wrapper -}}
+        ''')
+        assert t.render() == '[1][2][3][4]<FOO>'
+
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) %}
+            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+            {{- wrapper() }}
+        {%- endfor %}
+        {%- set wrapper = "<FOO>" %}
+        {{- wrapper -}}
+        ''')
+        assert t.render() == '[1][2][3][4]<FOO>'
+
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) %}
+            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+            {{- wrapper() }}
+        {%- endfor %}
+        {{- wrapper -}}
+        ''')
+        assert t.render(wrapper=23) == '[1][2][3][4]23'
+
+
+class BugTestCase(JinjaTestCase):
+
+    def test_keyword_folding(self):
+        env = Environment()
+        env.filters['testing'] = lambda value, some: value + some
+        assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
+               .render() == 'teststuff'
+
+    def test_extends_output_bugs(self):
+        env = Environment(loader=DictLoader({
+            'parent.html': '(({% block title %}{% endblock %}))'
+        }))
+
+        t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
+                            '[[{% block title %}title{% endblock %}]]'
+                            '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
+        assert t.render(expr=False) == '[[title]](1)(2)(3)'
+        assert t.render(expr=True) == '((title))'
+
+    def test_urlize_filter_escaping(self):
+        tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
+        assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">http://www.example.org/&lt;foo</a>'
+
+    def test_loop_call_loop(self):
+        tmpl = env.from_string('''
+
+        {% macro test() %}
+            {{ caller() }}
+        {% endmacro %}
+
+        {% for num1 in range(5) %}
+            {% call test() %}
+                {% for num2 in range(10) %}
+                    {{ loop.index }}
+                {% endfor %}
+            {% endcall %}
+        {% endfor %}
+
+        ''')
+
+        assert tmpl.render().split() == map(unicode, range(1, 11)) * 5
+
+    def test_weird_inline_comment(self):
+        env = Environment(line_statement_prefix='%')
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '% for item in seq {# missing #}\n...% endfor')
+
+    def test_old_macro_loop_scoping_bug(self):
+        tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
+                               '{% macro i() %}3{% endmacro %}{{ i() }}')
+        assert tmpl.render() == '123'
+
+    def test_partial_conditional_assignments(self):
+        tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
+        assert tmpl.render(a=23) == '23'
+        assert tmpl.render(b=True) == '42'
+
+    def test_stacked_locals_scoping_bug(self):
+        env = Environment(line_statement_prefix='#')
+        t = env.from_string('''\
+# for j in [1, 2]:
+#   set x = 1
+#   for i in [1, 2]:
+#     print x
+#     if i % 2 == 0:
+#       set x = x + 1
+#     endif
+#   endfor
+# endfor
+# if a
+#   print 'A'
+# elif b
+#   print 'B'
+# elif c == d
+#   print 'C'
+# else
+#   print 'D'
+# endif
+    ''')
+        assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
+
+    def test_stacked_locals_scoping_bug_twoframe(self):
+        t = Template('''
+            {% set x = 1 %}
+            {% for item in foo %}
+                {% if item == 1 %}
+                    {% set x = 2 %}
+                {% endif %}
+            {% endfor %}
+            {{ x }}
+        ''')
+        rv = t.render(foo=[1]).strip()
+        assert rv == u'1'
+
+    def test_call_with_args(self):
+        t = Template("""{% macro dump_users(users) -%}
+        <ul>
+          {%- for user in users -%}
+            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+          {%- endfor -%}
+          </ul>
+        {%- endmacro -%}
+
+        {% call(user) dump_users(list_of_user) -%}
+          <dl>
+            <dl>Realname</dl>
+            <dd>{{ user.realname|e }}</dd>
+            <dl>Description</dl>
+            <dd>{{ user.description }}</dd>
+          </dl>
+        {% endcall %}""")
+
+        assert [x.strip() for x in t.render(list_of_user=[{
+            'username':'apo',
+            'realname':'something else',
+            'description':'test'
+        }]).splitlines()] == [
+            u'<ul><li><p>apo</p><dl>',
+            u'<dl>Realname</dl>',
+            u'<dd>something else</dd>',
+            u'<dl>Description</dl>',
+            u'<dd>test</dd>',
+            u'</dl>',
+            u'</li></ul>'
+        ]
+
+    def test_empty_if_condition_fails(self):
+        self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
+        self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
+        self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
+
+    def test_recursive_loop_bug(self):
+        tpl1 = Template("""
+        {% for p in foo recursive%}
+            {{p.bar}}
+            {% for f in p.fields recursive%}
+                {{f.baz}}
+                {{p.bar}}
+                {% if f.rec %}
+                    {{ loop(f.sub) }}
+                {% endif %}
+            {% endfor %}
+        {% endfor %}
+        """)
+
+        tpl2 = Template("""
+        {% for p in foo%}
+            {{p.bar}}
+            {% for f in p.fields recursive%}
+                {{f.baz}}
+                {{p.bar}}
+                {% if f.rec %}
+                    {{ loop(f.sub) }}
+                {% endif %}
+            {% endfor %}
+        {% endfor %}
+        """)
+
+    def test_correct_prefix_loader_name(self):
+        env = Environment(loader=PrefixLoader({
+            'foo':  DictLoader({})
+        }))
+        try:
+            env.get_template('foo/bar.html')
+        except TemplateNotFound, e:
+            assert e.name == 'foo/bar.html'
+        else:
+            assert False, 'expected error here'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(CornerTestCase))
+    suite.addTest(unittest.makeSuite(BugTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html
new file mode 100644
index 0000000..77669fa
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html
@@ -0,0 +1,3 @@
+Before
+{{ fail() }}
+After

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html
new file mode 100644
index 0000000..b7d6715
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html
@@ -0,0 +1 @@
+FOO

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html
new file mode 100644
index 0000000..f21b817
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html
@@ -0,0 +1,4 @@
+Foo
+{% for item in broken %}
+  ...
+{% endif %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html
new file mode 100644
index 0000000..ba578e4
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html
@@ -0,0 +1 @@
+BAR

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py
new file mode 100644
index 0000000..b2b4cf1
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.security
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Checks the sandbox and other security features.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment
+from jinja2.sandbox import SandboxedEnvironment, \
+     ImmutableSandboxedEnvironment, unsafe
+from jinja2 import Markup, escape
+from jinja2.exceptions import SecurityError, TemplateSyntaxError
+
+
+class PrivateStuff(object):
+
+    def bar(self):
+        return 23
+
+    @unsafe
+    def foo(self):
+        return 42
+
+    def __repr__(self):
+        return 'PrivateStuff'
+
+
+class PublicStuff(object):
+    bar = lambda self: 23
+    _foo = lambda self: 42
+
+    def __repr__(self):
+        return 'PublicStuff'
+
+
+class SandboxTestCase(JinjaTestCase):
+
+    def test_unsafe(self):
+        env = SandboxedEnvironment()
+        self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
+                           foo=PrivateStuff())
+        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
+
+        self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
+                           foo=PublicStuff())
+        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
+        self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
+        self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
+        self.assert_raises(SecurityError, env.from_string(
+            "{{ foo.__class__.__subclasses__() }}").render, foo=42)
+
+    def test_immutable_environment(self):
+        env = ImmutableSandboxedEnvironment()
+        self.assert_raises(SecurityError, env.from_string(
+            '{{ [].append(23) }}').render)
+        self.assert_raises(SecurityError, env.from_string(
+            '{{ {1:2}.clear() }}').render)
+
+    def test_restricted(self):
+        env = SandboxedEnvironment()
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                      "{% for item.attribute in seq %}...{% endfor %}")
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                      "{% for foo, bar.baz in seq %}...{% endfor %}")
+
+    def test_markup_operations(self):
+        # adding two strings should escape the unsafe one
+        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+        safe = Markup('<em>username</em>')
+        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
+
+        # string interpolations are safe to use too
+        assert Markup('<em>%s</em>') % '<bad user>' == \
+               '<em>&lt;bad user&gt;</em>'
+        assert Markup('<em>%(username)s</em>') % {
+            'username': '<bad user>'
+        } == '<em>&lt;bad user&gt;</em>'
+
+        # an escaped object is markup too
+        assert type(Markup('foo') + 'bar') is Markup
+
+        # and it implements __html__ by returning itself
+        x = Markup("foo")
+        assert x.__html__() is x
+
+        # it also knows how to treat __html__ objects
+        class Foo(object):
+            def __html__(self):
+                return '<em>awesome</em>'
+            def __unicode__(self):
+                return 'awesome'
+        assert Markup(Foo()) == '<em>awesome</em>'
+        assert Markup('<strong>%s</strong>') % Foo() == \
+               '<strong><em>awesome</em></strong>'
+
+        # escaping and unescaping
+        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+        assert Markup("&lt;test&gt;").unescape() == "<test>"
+
+
+    def test_template_data(self):
+        env = Environment(autoescape=True)
+        t = env.from_string('{% macro say_hello(name) %}'
+                            '<p>Hello {{ name }}!</p>{% endmacro %}'
+                            '{{ say_hello("<blink>foo</blink>") }}')
+        escaped_out = '<p>Hello &lt;blink&gt;foo&lt;/blink&gt;!</p>'
+        assert t.render() == escaped_out
+        assert unicode(t.module) == escaped_out
+        assert escape(t.module) == escaped_out
+        assert t.module.say_hello('<blink>foo</blink>') == escaped_out
+        assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
+
+
+    def test_attr_filter(self):
+        env = SandboxedEnvironment()
+        tmpl = env.from_string('{{ 42|attr("__class__")|attr("__subclasses__")() }}')
+        self.assert_raises(SecurityError, tmpl.render)
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(SandboxTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py
new file mode 100644
index 0000000..cd5006f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.tests
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Who tests the tests?
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import unittest
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Markup, Environment
+
+env = Environment()
+
+
+class TestsTestCase(JinjaTestCase):
+
+    def test_defined(self):
+        tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
+        assert tmpl.render() == 'False|True'
+
+    def test_even(self):
+        tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
+        assert tmpl.render() == 'False|True'
+
+    def test_odd(self):
+        tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
+        assert tmpl.render() == 'True|False'
+
+    def test_lower(self):
+        tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
+        assert tmpl.render() == 'True|False'
+
+    def test_typechecks(self):
+        tmpl = env.from_string('''
+            {{ 42 is undefined }}
+            {{ 42 is defined }}
+            {{ 42 is none }}
+            {{ none is none }}
+            {{ 42 is number }}
+            {{ 42 is string }}
+            {{ "foo" is string }}
+            {{ "foo" is sequence }}
+            {{ [1] is sequence }}
+            {{ range is callable }}
+            {{ 42 is callable }}
+            {{ range(5) is iterable }}
+        ''')
+        assert tmpl.render().split() == [
+            'False', 'True', 'False', 'True', 'True', 'False',
+            'True', 'True', 'True', 'True', 'False', 'True'
+        ]
+
+    def test_sequence(self):
+        tmpl = env.from_string(
+            '{{ [1, 2, 3] is sequence }}|'
+            '{{ "foo" is sequence }}|'
+            '{{ 42 is sequence }}'
+        )
+        assert tmpl.render() == 'True|True|False'
+
+    def test_upper(self):
+        tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
+        assert tmpl.render() == 'True|False'
+
+    def test_sameas(self):
+        tmpl = env.from_string('{{ foo is sameas false }}|'
+                               '{{ 0 is sameas false }}')
+        assert tmpl.render(foo=False) == 'True|False'
+
+    def test_no_paren_for_arg1(self):
+        tmpl = env.from_string('{{ foo is sameas none }}')
+        assert tmpl.render(foo=None) == 'True'
+
+    def test_escaped(self):
+        env = Environment(autoescape=True)
+        tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
+        assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(TestsTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py
new file mode 100644
index 0000000..a402bbc
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.utils
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests utilities jinja uses.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import gc
+import unittest
+
+import pickle
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, Undefined, DebugUndefined, \
+     StrictUndefined, UndefinedError, Template, meta
+from jinja2.utils import LRUCache, escape, object_type_repr
+
+
+class LRUCacheTestCase(JinjaTestCase):
+
+    def test_simple(self):
+        d = LRUCache(3)
+        d["a"] = 1
+        d["b"] = 2
+        d["c"] = 3
+        d["a"]
+        d["d"] = 4
+        assert len(d) == 3
+        assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d
+
+    def test_pickleable(self):
+        cache = LRUCache(2)
+        cache["foo"] = 42
+        cache["bar"] = 23
+        cache["foo"]
+
+        for protocol in range(3):
+            copy = pickle.loads(pickle.dumps(cache, protocol))
+            assert copy.capacity == cache.capacity
+            assert copy._mapping == cache._mapping
+            assert copy._queue == cache._queue
+
+
+class HelpersTestCase(JinjaTestCase):
+
+    def test_object_type_repr(self):
+        class X(object):
+            pass
+        self.assert_equal(object_type_repr(42), 'int object')
+        self.assert_equal(object_type_repr([]), 'list object')
+        self.assert_equal(object_type_repr(X()),
+                         'jinja2.testsuite.utils.X object')
+        self.assert_equal(object_type_repr(None), 'None')
+        self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
+
+
+class MarkupLeakTestCase(JinjaTestCase):
+
+    def test_markup_leaks(self):
+        counts = set()
+        for count in xrange(20):
+            for item in xrange(1000):
+                escape("foo")
+                escape("<foo>")
+                escape(u"foo")
+                escape(u"<foo>")
+            counts.add(len(gc.get_objects()))
+        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(LRUCacheTestCase))
+    suite.addTest(unittest.makeSuite(HelpersTestCase))
+
+    # this test only tests the c extension
+    if not hasattr(escape, 'func_code'):
+        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
+
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/utils.py b/ambari-common/src/main/python/jinja2/jinja2/utils.py
new file mode 100644
index 0000000..7b77b8e
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/utils.py
@@ -0,0 +1,601 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.utils
+    ~~~~~~~~~~~~
+
+    Utility functions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import sys
+import errno
+try:
+    from thread import allocate_lock
+except ImportError:
+    from dummy_thread import allocate_lock
+from collections import deque
+from itertools import imap
+
+
+_word_split_re = re.compile(r'(\s+)')
+_punctuation_re = re.compile(
+    '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
+        '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
+        '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
+    )
+)
+_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^;]+);')
+_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+_digits = '0123456789'
+
+# special singleton representing missing values for the runtime
+missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
+
+# internal code
+internal_code = set()
+
+
+# concatenate a list of strings and convert them to unicode.
+# unfortunately there is a bug in python 2.4 and lower that causes
+# unicode.join trash the traceback.
+_concat = u''.join
+try:
+    def _test_gen_bug():
+        raise TypeError(_test_gen_bug)
+        yield None
+    _concat(_test_gen_bug())
+except TypeError, _error:
+    if not _error.args or _error.args[0] is not _test_gen_bug:
+        def concat(gen):
+            try:
+                return _concat(list(gen))
+            except:
+                # this hack is needed so that the current frame
+                # does not show up in the traceback.
+                exc_type, exc_value, tb = sys.exc_info()
+                raise exc_type, exc_value, tb.tb_next
+    else:
+        concat = _concat
+    del _test_gen_bug, _error
+
+
+# for python 2.x we create outselves a next() function that does the
+# basics without exception catching.
+try:
+    next = next
+except NameError:
+    def next(x):
+        return x.next()
+
+
+# if this python version is unable to deal with unicode filenames
+# when passed to encode we let this function encode it properly.
+# This is used in a couple of places.  As far as Jinja is concerned
+# filenames are unicode *or* bytestrings in 2.x and unicode only in
+# 3.x because compile cannot handle bytes
+if sys.version_info < (3, 0):
+    def _encode_filename(filename):
+        if isinstance(filename, unicode):
+            return filename.encode('utf-8')
+        return filename
+else:
+    def _encode_filename(filename):
+        assert filename is None or isinstance(filename, str), \
+            'filenames must be strings'
+        return filename
+
+from keyword import iskeyword as is_python_keyword
+
+
+# common types.  These do exist in the special types module too which however
+# does not exist in IronPython out of the box.  Also that way we don't have
+# to deal with implementation specific stuff here
+class _C(object):
+    def method(self): pass
+def _func():
+    yield None
+FunctionType = type(_func)
+GeneratorType = type(_func())
+MethodType = type(_C.method)
+CodeType = type(_C.method.func_code)
+try:
+    raise TypeError()
+except TypeError:
+    _tb = sys.exc_info()[2]
+    TracebackType = type(_tb)
+    FrameType = type(_tb.tb_frame)
+del _C, _tb, _func
+
+
+def contextfunction(f):
+    """This decorator can be used to mark a function or method context callable.
+    A context callable is passed the active :class:`Context` as first argument when
+    called from the template.  This is useful if a function wants to get access
+    to the context or functions provided on the context object.  For example
+    a function that returns a sorted list of template variables the current
+    template exports could look like this::
+
+        @contextfunction
+        def get_exported_names(context):
+            return sorted(context.exported_vars)
+    """
+    f.contextfunction = True
+    return f
+
+
+def evalcontextfunction(f):
+    """This decoraotr can be used to mark a function or method as an eval
+    context callable.  This is similar to the :func:`contextfunction`
+    but instead of passing the context, an evaluation context object is
+    passed.  For more information about the eval context, see
+    :ref:`eval-context`.
+
+    .. versionadded:: 2.4
+    """
+    f.evalcontextfunction = True
+    return f
+
+
+def environmentfunction(f):
+    """This decorator can be used to mark a function or method as environment
+    callable.  This decorator works exactly like the :func:`contextfunction`
+    decorator just that the first argument is the active :class:`Environment`
+    and not context.
+    """
+    f.environmentfunction = True
+    return f
+
+
+def internalcode(f):
+    """Marks the function as internally used"""
+    internal_code.add(f.func_code)
+    return f
+
+
+def is_undefined(obj):
+    """Check if the object passed is undefined.  This does nothing more than
+    performing an instance check against :class:`Undefined` but looks nicer.
+    This can be used for custom filters or tests that want to react to
+    undefined variables.  For example a custom default filter can look like
+    this::
+
+        def default(var, default=''):
+            if is_undefined(var):
+                return default
+            return var
+    """
+    from jinja2.runtime import Undefined
+    return isinstance(obj, Undefined)
+
+
+def consume(iterable):
+    """Consumes an iterable without doing anything with it."""
+    for event in iterable:
+        pass
+
+
+def clear_caches():
+    """Jinja2 keeps internal caches for environments and lexers.  These are
+    used so that Jinja2 doesn't have to recreate environments and lexers all
+    the time.  Normally you don't have to care about that but if you are
+    messuring memory consumption you may want to clean the caches.
+    """
+    from jinja2.environment import _spontaneous_environments
+    from jinja2.lexer import _lexer_cache
+    _spontaneous_environments.clear()
+    _lexer_cache.clear()
+
+
+def import_string(import_name, silent=False):
+    """Imports an object based on a string.  This use useful if you want to
+    use import paths as endpoints or something similar.  An import path can
+    be specified either in dotted notation (``xml.sax.saxutils.escape``)
+    or with a colon as object delimiter (``xml.sax.saxutils:escape``).
+
+    If the `silent` is True the return value will be `None` if the import
+    fails.
+
+    :return: imported object
+    """
+    try:
+        if ':' in import_name:
+            module, obj = import_name.split(':', 1)
+        elif '.' in import_name:
+            items = import_name.split('.')
+            module = '.'.join(items[:-1])
+            obj = items[-1]
+        else:
+            return __import__(import_name)
+        return getattr(__import__(module, None, None, [obj]), obj)
+    except (ImportError, AttributeError):
+        if not silent:
+            raise
+
+
+def open_if_exists(filename, mode='rb'):
+    """Returns a file descriptor for the filename if that file exists,
+    otherwise `None`.
+    """
+    try:
+        return open(filename, mode)
+    except IOError, e:
+        if e.errno not in (errno.ENOENT, errno.EISDIR):
+            raise
+
+
+def object_type_repr(obj):
+    """Returns the name of the object's type.  For some recognized
+    singletons the name of the object is returned instead. (For
+    example for `None` and `Ellipsis`).
+    """
+    if obj is None:
+        return 'None'
+    elif obj is Ellipsis:
+        return 'Ellipsis'
+    # __builtin__ in 2.x, builtins in 3.x
+    if obj.__class__.__module__ in ('__builtin__', 'builtins'):
+        name = obj.__class__.__name__
+    else:
+        name = obj.__class__.__module__ + '.' + obj.__class__.__name__
+    return '%s object' % name
+
+
+def pformat(obj, verbose=False):
+    """Prettyprint an object.  Either use the `pretty` library or the
+    builtin `pprint`.
+    """
+    try:
+        from pretty import pretty
+        return pretty(obj, verbose=verbose)
+    except ImportError:
+        from pprint import pformat
+        return pformat(obj)
+
+
+def urlize(text, trim_url_limit=None, nofollow=False):
+    """Converts any URLs in text into clickable links. Works on http://,
+    https:// and www. links. Links can have trailing punctuation (periods,
+    commas, close-parens) and leading punctuation (opening parens) and
+    it'll still do the right thing.
+
+    If trim_url_limit is not None, the URLs in link text will be limited
+    to trim_url_limit characters.
+
+    If nofollow is True, the URLs in link text will get a rel="nofollow"
+    attribute.
+    """
+    trim_url = lambda x, limit=trim_url_limit: limit is not None \
+                         and (x[:limit] + (len(x) >=limit and '...'
+                         or '')) or x
+    words = _word_split_re.split(unicode(escape(text)))
+    nofollow_attr = nofollow and ' rel="nofollow"' or ''
+    for i, word in enumerate(words):
+        match = _punctuation_re.match(word)
+        if match:
+            lead, middle, trail = match.groups()
+            if middle.startswith('www.') or (
+                '@' not in middle and
+                not middle.startswith('http://') and
+                len(middle) > 0 and
+                middle[0] in _letters + _digits and (
+                    middle.endswith('.org') or
+                    middle.endswith('.net') or
+                    middle.endswith('.com')
+                )):
+                middle = '<a href="http://%s"%s>%s</a>' % (middle,
+                    nofollow_attr, trim_url(middle))
+            if middle.startswith('http://') or \
+               middle.startswith('https://'):
+                middle = '<a href="%s"%s>%s</a>' % (middle,
+                    nofollow_attr, trim_url(middle))
+            if '@' in middle and not middle.startswith('www.') and \
+               not ':' in middle and _simple_email_re.match(middle):
+                middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
+            if lead + middle + trail != word:
+                words[i] = lead + middle + trail
+    return u''.join(words)
+
+
+def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
+    """Generate some lorem impsum for the template."""
+    from jinja2.constants import LOREM_IPSUM_WORDS
+    from random import choice, randrange
+    words = LOREM_IPSUM_WORDS.split()
+    result = []
+
+    for _ in xrange(n):
+        next_capitalized = True
+        last_comma = last_fullstop = 0
+        word = None
+        last = None
+        p = []
+
+        # each paragraph contains out of 20 to 100 words.
+        for idx, _ in enumerate(xrange(randrange(min, max))):
+            while True:
+                word = choice(words)
+                if word != last:
+                    last = word
+                    break
+            if next_capitalized:
+                word = word.capitalize()
+                next_capitalized = False
+            # add commas
+            if idx - randrange(3, 8) > last_comma:
+                last_comma = idx
+                last_fullstop += 2
+                word += ','
+            # add end of sentences
+            if idx - randrange(10, 20) > last_fullstop:
+                last_comma = last_fullstop = idx
+                word += '.'
+                next_capitalized = True
+            p.append(word)
+
+        # ensure that the paragraph ends with a dot.
+        p = u' '.join(p)
+        if p.endswith(','):
+            p = p[:-1] + '.'
+        elif not p.endswith('.'):
+            p += '.'
+        result.append(p)
+
+    if not html:
+        return u'\n\n'.join(result)
+    return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
+
+
+class LRUCache(object):
+    """A simple LRU Cache implementation."""
+
+    # this is fast for small capacities (something below 1000) but doesn't
+    # scale.  But as long as it's only used as storage for templates this
+    # won't do any harm.
+
+    def __init__(self, capacity):
+        self.capacity = capacity
+        self._mapping = {}
+        self._queue = deque()
+        self._postinit()
+
+    def _postinit(self):
+        # alias all queue methods for faster lookup
+        self._popleft = self._queue.popleft
+        self._pop = self._queue.pop
+        if hasattr(self._queue, 'remove'):
+            self._remove = self._queue.remove
+        self._wlock = allocate_lock()
+        self._append = self._queue.append
+
+    def _remove(self, obj):
+        """Python 2.4 compatibility."""
+        for idx, item in enumerate(self._queue):
+            if item == obj:
+                del self._queue[idx]
+                break
+
+    def __getstate__(self):
+        return {
+            'capacity':     self.capacity,
+            '_mapping':     self._mapping,
+            '_queue':       self._queue
+        }
+
+    def __setstate__(self, d):
+        self.__dict__.update(d)
+        self._postinit()
+
+    def __getnewargs__(self):
+        return (self.capacity,)
+
+    def copy(self):
+        """Return an shallow copy of the instance."""
+        rv = self.__class__(self.capacity)
+        rv._mapping.update(self._mapping)
+        rv._queue = deque(self._queue)
+        return rv
+
+    def get(self, key, default=None):
+        """Return an item from the cache dict or `default`"""
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def setdefault(self, key, default=None):
+        """Set `default` if the key is not in the cache otherwise
+        leave unchanged. Return the value of this key.
+        """
+        try:
+            return self[key]
+        except KeyError:
+            self[key] = default
+            return default
+
+    def clear(self):
+        """Clear the cache."""
+        self._wlock.acquire()
+        try:
+            self._mapping.clear()
+            self._queue.clear()
+        finally:
+            self._wlock.release()
+
+    def __contains__(self, key):
+        """Check if a key exists in this cache."""
+        return key in self._mapping
+
+    def __len__(self):
+        """Return the current size of the cache."""
+        return len(self._mapping)
+
+    def __repr__(self):
+        return '<%s %r>' % (
+            self.__class__.__name__,
+            self._mapping
+        )
+
+    def __getitem__(self, key):
+        """Get an item from the cache. Moves the item up so that it has the
+        highest priority then.
+
+        Raise an `KeyError` if it does not exist.
+        """
+        rv = self._mapping[key]
+        if self._queue[-1] != key:
+            try:
+                self._remove(key)
+            except ValueError:
+                # if something removed the key from the container
+                # when we read, ignore the ValueError that we would
+                # get otherwise.
+                pass
+            self._append(key)
+        return rv
+
+    def __setitem__(self, key, value):
+        """Sets the value for an item. Moves the item up so that it
+        has the highest priority then.
+        """
+        self._wlock.acquire()
+        try:
+            if key in self._mapping:
+                try:
+                    self._remove(key)
+                except ValueError:
+                    # __getitem__ is not locked, it might happen
+                    pass
+            elif len(self._mapping) == self.capacity:
+                del self._mapping[self._popleft()]
+            self._append(key)
+            self._mapping[key] = value
+        finally:
+            self._wlock.release()
+
+    def __delitem__(self, key):
+        """Remove an item from the cache dict.
+        Raise an `KeyError` if it does not exist.
+        """
+        self._wlock.acquire()
+        try:
+            del self._mapping[key]
+            try:
+                self._remove(key)
+            except ValueError:
+                # __getitem__ is not locked, it might happen
+                pass
+        finally:
+            self._wlock.release()
+
+    def items(self):
+        """Return a list of items."""
+        result = [(key, self._mapping[key]) for key in list(self._queue)]
+        result.reverse()
+        return result
+
+    def iteritems(self):
+        """Iterate over all items."""
+        return iter(self.items())
+
+    def values(self):
+        """Return a list of all values."""
+        return [x[1] for x in self.items()]
+
+    def itervalue(self):
+        """Iterate over all values."""
+        return iter(self.values())
+
+    def keys(self):
+        """Return a list of all keys ordered by most recent usage."""
+        return list(self)
+
+    def iterkeys(self):
+        """Iterate over all keys in the cache dict, ordered by
+        the most recent usage.
+        """
+        return reversed(tuple(self._queue))
+
+    __iter__ = iterkeys
+
+    def __reversed__(self):
+        """Iterate over the values in the cache dict, oldest items
+        coming first.
+        """
+        return iter(tuple(self._queue))
+
+    __copy__ = copy
+
+
+# register the LRU cache as mutable mapping if possible
+try:
+    from collections import MutableMapping
+    MutableMapping.register(LRUCache)
+except ImportError:
+    pass
+
+
+class Cycler(object):
+    """A cycle helper for templates."""
+
+    def __init__(self, *items):
+        if not items:
+            raise RuntimeError('at least one item has to be provided')
+        self.items = items
+        self.reset()
+
+    def reset(self):
+        """Resets the cycle."""
+        self.pos = 0
+
+    @property
+    def current(self):
+        """Returns the current item."""
+        return self.items[self.pos]
+
+    def next(self):
+        """Goes one item ahead and returns it."""
+        rv = self.current
+        self.pos = (self.pos + 1) % len(self.items)
+        return rv
+
+
+class Joiner(object):
+    """A joining helper for templates."""
+
+    def __init__(self, sep=u', '):
+        self.sep = sep
+        self.used = False
+
+    def __call__(self):
+        if not self.used:
+            self.used = True
+            return u''
+        return self.sep
+
+
+# try markupsafe first, if that fails go with Jinja2's bundled version
+# of markupsafe.  Markupsafe was previously Jinja2's implementation of
+# the Markup object but was moved into a separate package in a patchleve
+# release
+try:
+    from markupsafe import Markup, escape, soft_unicode
+except ImportError:
+    from jinja2._markupsafe import Markup, escape, soft_unicode
+
+
+# partials
+try:
+    from functools import partial
+except ImportError:
+    class partial(object):
+        def __init__(self, _func, *args, **kwargs):
+            self._func = _func
+            self._args = args
+            self._kwargs = kwargs
+        def __call__(self, *args, **kwargs):
+            kwargs.update(self._kwargs)
+            return self._func(*(self._args + args), **kwargs)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/visitor.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/visitor.py b/ambari-common/src/main/python/jinja2/jinja2/visitor.py
new file mode 100644
index 0000000..413e7c3
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/visitor.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.visitor
+    ~~~~~~~~~~~~~~
+
+    This module implements a visitor for the nodes.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from jinja2.nodes import Node
+
+
+class NodeVisitor(object):
+    """Walks the abstract syntax tree and call visitor functions for every
+    node found.  The visitor functions may return values which will be
+    forwarded by the `visit` method.
+
+    Per default the visitor functions for the nodes are ``'visit_'`` +
+    class name of the node.  So a `TryFinally` node visit function would
+    be `visit_TryFinally`.  This behavior can be changed by overriding
+    the `get_visitor` function.  If no visitor function exists for a node
+    (return value `None`) the `generic_visit` visitor is used instead.
+    """
+
+    def get_visitor(self, node):
+        """Return the visitor function for this node or `None` if no visitor
+        exists for this node.  In that case the generic visit function is
+        used instead.
+        """
+        method = 'visit_' + node.__class__.__name__
+        return getattr(self, method, None)
+
+    def visit(self, node, *args, **kwargs):
+        """Visit a node."""
+        f = self.get_visitor(node)
+        if f is not None:
+            return f(node, *args, **kwargs)
+        return self.generic_visit(node, *args, **kwargs)
+
+    def generic_visit(self, node, *args, **kwargs):
+        """Called if no explicit visitor function exists for a node."""
+        for node in node.iter_child_nodes():
+            self.visit(node, *args, **kwargs)
+
+
+class NodeTransformer(NodeVisitor):
+    """Walks the abstract syntax tree and allows modifications of nodes.
+
+    The `NodeTransformer` will walk the AST and use the return value of the
+    visitor functions to replace or remove the old node.  If the return
+    value of the visitor function is `None` the node will be removed
+    from the previous location otherwise it's replaced with the return
+    value.  The return value may be the original node in which case no
+    replacement takes place.
+    """
+
+    def generic_visit(self, node, *args, **kwargs):
+        for field, old_value in node.iter_fields():
+            if isinstance(old_value, list):
+                new_values = []
+                for value in old_value:
+                    if isinstance(value, Node):
+                        value = self.visit(value, *args, **kwargs)
+                        if value is None:
+                            continue
+                        elif not isinstance(value, Node):
+                            new_values.extend(value)
+                            continue
+                    new_values.append(value)
+                old_value[:] = new_values
+            elif isinstance(old_value, Node):
+                new_node = self.visit(old_value, *args, **kwargs)
+                if new_node is None:
+                    delattr(node, field)
+                else:
+                    setattr(node, field, new_node)
+        return node
+
+    def visit_list(self, node, *args, **kwargs):
+        """As transformers may return lists in some places this method
+        can be used to enforce a list as return value.
+        """
+        rv = self.visit(node, *args, **kwargs)
+        if not isinstance(rv, list):
+            rv = [rv]
+        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/scripts/pylintrc
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/scripts/pylintrc b/ambari-common/src/main/python/jinja2/scripts/pylintrc
new file mode 100644
index 0000000..4f85b49
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/scripts/pylintrc
@@ -0,0 +1,301 @@
+# lint Python modules using external checkers.
+# 
+# This is the main checker controling the other ones and the reports
+# generation. It is itself both a raw checker and an astng checker in order
+# to:
+# * handle message activation / deactivation at the module level
+# * handle some basic but necessary stats'data (number of classes, methods...)
+# 
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Profiled execution.
+profile=no
+
+# Add <file or directory> to the black list. It should be a base name, not a
+# path. You may set this option multiple times.
+ignore=.svn
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Set the cache size for astng objects.
+cache-size=500
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable only checker(s) with the given id(s). This option conflict with the
+# disable-checker option
+#enable-checker=
+
+# Enable all checker(s) except those with the given id(s). This option conflict
+# with the disable-checker option
+#disable-checker=
+
+# Enable all messages in the listed categories.
+#enable-msg-cat=
+
+# Disable all messages in the listed categories.
+#disable-msg-cat=
+
+# Enable the message(s) with the given id(s).
+#enable-msg=
+
+# Disable the message(s) with the given id(s).
+disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201
+
+
+[REPORTS]
+
+# set the output format. Available formats are text, parseable, colorized and
+# html
+output-format=colorized
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells wether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note).You have access to the variables errors warning, statement which
+# respectivly contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (R0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (R0004).
+comment=no
+
+# Enable the report(s) with the given id(s).
+#enable-report=
+
+# Disable the report(s) with the given id(s).
+#disable-report=
+
+
+# checks for
+# * unused variables / imports
+# * undefined variables
+# * redefinition of variable from builtins or from an outer scope
+# * use of variable before assigment
+# 
+[VARIABLES]
+
+# Tells wether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching names used for dummy variables (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+# try to find bugs in the code using type inference
+# 
+[TYPECHECK]
+
+# Tells wether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# When zope mode is activated, consider the acquired-members option to ignore
+# access to some undefined attributes.
+zope=no
+
+# List of members which are usually get through zope's acquisition mecanism and
+# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
+acquired-members=REQUEST,acl_users,aq_parent
+
+
+# checks for :
+# * doc strings
+# * modules / classes / functions / methods / arguments / variables name
+# * number of arguments, local variables, branchs, returns and statements in
+# functions, methods
+# * required module attributes
+# * dangerous default values as arguments
+# * redefinition of function / method / class
+# * uses of the global statement
+# 
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=apply,input
+
+
+# checks for sign of poor/misdesign:
+# * number of methods, attributes, local variables...
+# * size, complexity of functions, methods
+# 
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=12
+
+# Maximum number of locals for function / method body
+max-locals=30
+
+# Maximum number of return / yield for function / method body
+max-returns=12
+
+# Maximum number of branch for function / method body
+max-branchs=30
+
+# Maximum number of statements in function / method body
+max-statements=60
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=20
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+# checks for
+# * external modules dependencies
+# * relative / wildcard imports
+# * cyclic imports
+# * uses of deprecated modules
+# 
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report R0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report R0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report R0402 must
+# not be disabled)
+int-import-graph=
+
+
+# checks for :
+# * methods without self as first argument
+# * overridden methods signature
+# * access only to existant members via self
+# * attributes not defined in the __init__ method
+# * supported interfaces implementation
+# * unreachable code
+# 
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+
+# checks for similarities and duplicated code. This computation may be
+# memory / CPU intensive, so you should disable it if you experiments some
+# problems.
+# 
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=10
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+# checks for:
+# * warning notes in the code like FIXME, XXX
+# * PEP 263: source code with non ascii character but no encoding declaration
+# 
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+# checks for :
+# * unauthorized constructions
+# * strict indentation
+# * line length
+# * use of <> instead of !=
+# 
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=90
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/setup.cfg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/setup.cfg b/ambari-common/src/main/python/jinja2/setup.cfg
new file mode 100644
index 0000000..2d74c58
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/setup.cfg
@@ -0,0 +1,6 @@
+[egg_info]
+tag_build = dev
+tag_date = true
+
+[aliases]
+release = egg_info -RDb ''

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/setup.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/setup.py b/ambari-common/src/main/python/jinja2/setup.py
new file mode 100644
index 0000000..7956d19
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/setup.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+"""
+Jinja2
+~~~~~~
+
+Jinja2 is a template engine written in pure Python.  It provides a
+`Django`_ inspired non-XML syntax but supports inline expressions and
+an optional `sandboxed`_ environment.
+
+Nutshell
+--------
+
+Here a small example of a Jinja template::
+
+    {% extends 'base.html' %}
+    {% block title %}Memberlist{% endblock %}
+    {% block content %}
+      <ul>
+      {% for user in users %}
+        <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+      {% endfor %}
+      </ul>
+    {% endblock %}
+
+Philosophy
+----------
+
+Application logic is for the controller but don't try to make the life
+for the template designer too hard by giving him too few functionality.
+
+For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
+
+.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security)
+.. _Django: http://www.djangoproject.com/
+.. _Jinja2 webpage: http://jinja.pocoo.org/
+.. _documentation: http://jinja.pocoo.org/2/documentation/
+"""
+import sys
+
+from setuptools import setup, Extension, Feature
+
+debugsupport = Feature(
+    'optional C debug support',
+    standard=False,
+    ext_modules = [
+        Extension('jinja2._debugsupport', ['jinja2/_debugsupport.c']),
+    ],
+)
+
+
+# tell distribute to use 2to3 with our own fixers.
+extra = {}
+if sys.version_info >= (3, 0):
+    extra.update(
+        use_2to3=True,
+        use_2to3_fixers=['custom_fixers']
+    )
+
+# ignore the old '--with-speedups' flag
+try:
+    speedups_pos = sys.argv.index('--with-speedups')
+except ValueError:
+    pass
+else:
+    sys.argv[speedups_pos] = '--with-debugsupport'
+    sys.stderr.write('*' * 74 + '\n')
+    sys.stderr.write('WARNING:\n')
+    sys.stderr.write('  the --with-speedups flag is deprecated, assuming '
+                     '--with-debugsupport\n')
+    sys.stderr.write('  For the actual speedups install the MarkupSafe '
+                     'package.\n')
+    sys.stderr.write('*' * 74 + '\n')
+
+
+setup(
+    name='Jinja2',
+    version='2.5.5',
+    url='http://jinja.pocoo.org/',
+    license='BSD',
+    author='Armin Ronacher',
+    author_email='armin.ronacher@active-4.com',
+    description='A small but fast and easy to use stand-alone template '
+                'engine written in pure python.',
+    long_description=__doc__,
+    # jinja is egg safe. But we hate eggs
+    zip_safe=False,
+    classifiers=[
+        'Development Status :: 5 - Production/Stable',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 3',
+        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+        'Topic :: Text Processing :: Markup :: HTML'
+    ],
+    packages=['jinja2', 'jinja2.testsuite', 'jinja2.testsuite.res',
+              'jinja2._markupsafe'],
+    extras_require={'i18n': ['Babel>=0.8']},
+    test_suite='jinja2.testsuite.suite',
+    include_package_data=True,
+    entry_points="""
+    [babel.extractors]
+    jinja2 = jinja2.ext:babel_extract[i18n]
+    """,
+    features={'debugsupport': debugsupport},
+    **extra
+)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/resource_management/core/source.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/core/source.py b/ambari-common/src/main/python/resource_management/core/source.py
index 22e1c6d..c2a4c24 100644
--- a/ambari-common/src/main/python/resource_management/core/source.py
+++ b/ambari-common/src/main/python/resource_management/core/source.py
@@ -72,7 +72,7 @@ class StaticFile(Source):
 
 
 try:
-  from ambari_jinja2 import Environment as JinjaEnvironment, BaseLoader, TemplateNotFound, FunctionLoader, StrictUndefined
+  from jinja2 import Environment as JinjaEnvironment, BaseLoader, TemplateNotFound, FunctionLoader, StrictUndefined
 except ImportError:
   class Template(Source):
     def __init__(self, name, variables=None, env=None):

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index e6c2546..d7d2491 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -955,7 +955,7 @@
                 <argument>${custom.tests}</argument>
               </arguments>
               <environmentVariables>
-                  <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python:${project.basedir}/../ambari-agent/src/main/python:${project.basedir}/../ambari-common/src/main/python/ambari_jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/src/main/python:${project.basedir}/src/main/python/ambari-server-state:${project.basedir}/src/test/python:$PYTHONPATH</PYTHONPATH>
+                  <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python:${project.basedir}/../ambari-agent/src/main/python:${project.basedir}/../ambari-common/src/main/python/jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/src/main/python:${project.basedir}/src/main/python/ambari-server-state:${project.basedir}/src/test/python:$PYTHONPATH</PYTHONPATH>
               </environmentVariables>
               <skip>${skipTests}</skip>
             </configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-server/src/test/python/unitTests.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/unitTests.py b/ambari-server/src/test/python/unitTests.py
index 773a698..ab99cce 100644
--- a/ambari-server/src/test/python/unitTests.py
+++ b/ambari-server/src/test/python/unitTests.py
@@ -117,7 +117,7 @@ def main():
   ambari_agent_folder = os.path.join(ambari_server_folder,"../ambari-agent")
   ambari_common_folder = os.path.join(ambari_server_folder,"../ambari-common")
   sys.path.append(ambari_common_folder + "/src/main/python")
-  sys.path.append(ambari_common_folder + "/src/main/python/ambari_jinja2")
+  sys.path.append(ambari_common_folder + "/src/main/python/jinja2")
   sys.path.append(ambari_common_folder + "/src/main/python")
   sys.path.append(ambari_common_folder + "/src/test/python")
   sys.path.append(ambari_agent_folder + "/src/main/python")

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index d2373fb..bf62fd2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -204,7 +204,7 @@
             <!--Python Mock library (BSD license)-->
             <exclude>ambari-common/src/test/python/mock/**</exclude>
             <!--Jinja2 library (BSD license)-->
-            <exclude>ambari-common/src/main/python/ambari_jinja2/**</exclude>
+            <exclude>ambari-common/src/main/python/jinja2/**</exclude>
 
             <!--Contributions-->
             <exclude>contrib/ambari-scom/management-pack/Hadoop_MP/**</exclude>


[18/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py
deleted file mode 100644
index bdb545e..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py
+++ /dev/null
@@ -1,719 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.filters
-    ~~~~~~~~~~~~~~
-
-    Bundled jinja filters.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import math
-from random import choice
-from operator import itemgetter
-from itertools import imap, groupby
-from ambari_jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
-from ambari_jinja2.runtime import Undefined
-from ambari_jinja2.exceptions import FilterArgumentError, SecurityError
-
-
-_word_re = re.compile(r'\w+(?u)')
-
-
-def contextfilter(f):
-    """Decorator for marking context dependent filters. The current
-    :class:`Context` will be passed as first argument.
-    """
-    f.contextfilter = True
-    return f
-
-
-def evalcontextfilter(f):
-    """Decorator for marking eval-context dependent filters.  An eval
-    context object is passed as first argument.  For more information
-    about the eval context, see :ref:`eval-context`.
-
-    .. versionadded:: 2.4
-    """
-    f.evalcontextfilter = True
-    return f
-
-
-def environmentfilter(f):
-    """Decorator for marking evironment dependent filters.  The current
-    :class:`Environment` is passed to the filter as first argument.
-    """
-    f.environmentfilter = True
-    return f
-
-
-def do_forceescape(value):
-    """Enforce HTML escaping.  This will probably double escape variables."""
-    if hasattr(value, '__html__'):
-        value = value.__html__()
-    return escape(unicode(value))
-
-
-@evalcontextfilter
-def do_replace(eval_ctx, s, old, new, count=None):
-    """Return a copy of the value with all occurrences of a substring
-    replaced with a new one. The first argument is the substring
-    that should be replaced, the second is the replacement string.
-    If the optional third argument ``count`` is given, only the first
-    ``count`` occurrences are replaced:
-
-    .. sourcecode:: jinja
-
-        {{ "Hello World"|replace("Hello", "Goodbye") }}
-            -> Goodbye World
-
-        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
-            -> d'oh, d'oh, aaargh
-    """
-    if count is None:
-        count = -1
-    if not eval_ctx.autoescape:
-        return unicode(s).replace(unicode(old), unicode(new), count)
-    if hasattr(old, '__html__') or hasattr(new, '__html__') and \
-       not hasattr(s, '__html__'):
-        s = escape(s)
-    else:
-        s = soft_unicode(s)
-    return s.replace(soft_unicode(old), soft_unicode(new), count)
-
-
-def do_upper(s):
-    """Convert a value to uppercase."""
-    return soft_unicode(s).upper()
-
-
-def do_lower(s):
-    """Convert a value to lowercase."""
-    return soft_unicode(s).lower()
-
-
-@evalcontextfilter
-def do_xmlattr(_eval_ctx, d, autospace=True):
-    """Create an SGML/XML attribute string based on the items in a dict.
-    All values that are neither `none` nor `undefined` are automatically
-    escaped:
-
-    .. sourcecode:: html+jinja
-
-        <ul{{ {'class': 'my_list', 'missing': none,
-                'id': 'list-%d'|format(variable)}|xmlattr }}>
-        ...
-        </ul>
-
-    Results in something like this:
-
-    .. sourcecode:: html
-
-        <ul class="my_list" id="list-42">
-        ...
-        </ul>
-
-    As you can see it automatically prepends a space in front of the item
-    if the filter returned something unless the second parameter is false.
-    """
-    rv = u' '.join(
-        u'%s="%s"' % (escape(key), escape(value))
-        for key, value in d.iteritems()
-        if value is not None and not isinstance(value, Undefined)
-    )
-    if autospace and rv:
-        rv = u' ' + rv
-    if _eval_ctx.autoescape:
-        rv = Markup(rv)
-    return rv
-
-
-def do_capitalize(s):
-    """Capitalize a value. The first character will be uppercase, all others
-    lowercase.
-    """
-    return soft_unicode(s).capitalize()
-
-
-def do_title(s):
-    """Return a titlecased version of the value. I.e. words will start with
-    uppercase letters, all remaining characters are lowercase.
-    """
-    return soft_unicode(s).title()
-
-
-def do_dictsort(value, case_sensitive=False, by='key'):
-    """Sort a dict and yield (key, value) pairs. Because python dicts are
-    unsorted you may want to use this function to order them by either
-    key or value:
-
-    .. sourcecode:: jinja
-
-        {% for item in mydict|dictsort %}
-            sort the dict by key, case insensitive
-
-        {% for item in mydict|dicsort(true) %}
-            sort the dict by key, case sensitive
-
-        {% for item in mydict|dictsort(false, 'value') %}
-            sort the dict by key, case insensitive, sorted
-            normally and ordered by value.
-    """
-    if by == 'key':
-        pos = 0
-    elif by == 'value':
-        pos = 1
-    else:
-        raise FilterArgumentError('You can only sort by either '
-                                  '"key" or "value"')
-    def sort_func(item):
-        value = item[pos]
-        if isinstance(value, basestring) and not case_sensitive:
-            value = value.lower()
-        return value
-
-    return sorted(value.items(), key=sort_func)
-
-
-def do_sort(value, reverse=False, case_sensitive=False):
-    """Sort an iterable.  Per default it sorts ascending, if you pass it
-    true as first argument it will reverse the sorting.
-
-    If the iterable is made of strings the third parameter can be used to
-    control the case sensitiveness of the comparison which is disabled by
-    default.
-
-    .. sourcecode:: jinja
-
-        {% for item in iterable|sort %}
-            ...
-        {% endfor %}
-    """
-    if not case_sensitive:
-        def sort_func(item):
-            if isinstance(item, basestring):
-                item = item.lower()
-            return item
-    else:
-        sort_func = None
-    return sorted(value, key=sort_func, reverse=reverse)
-
-
-def do_default(value, default_value=u'', boolean=False):
-    """If the value is undefined it will return the passed default value,
-    otherwise the value of the variable:
-
-    .. sourcecode:: jinja
-
-        {{ my_variable|default('my_variable is not defined') }}
-
-    This will output the value of ``my_variable`` if the variable was
-    defined, otherwise ``'my_variable is not defined'``. If you want
-    to use default with variables that evaluate to false you have to
-    set the second parameter to `true`:
-
-    .. sourcecode:: jinja
-
-        {{ ''|default('the string was empty', true) }}
-    """
-    if (boolean and not value) or isinstance(value, Undefined):
-        return default_value
-    return value
-
-
-@evalcontextfilter
-def do_join(eval_ctx, value, d=u''):
-    """Return a string which is the concatenation of the strings in the
-    sequence. The separator between elements is an empty string per
-    default, you can define it with the optional parameter:
-
-    .. sourcecode:: jinja
-
-        {{ [1, 2, 3]|join('|') }}
-            -> 1|2|3
-
-        {{ [1, 2, 3]|join }}
-            -> 123
-    """
-    # no automatic escaping?  joining is a lot eaiser then
-    if not eval_ctx.autoescape:
-        return unicode(d).join(imap(unicode, value))
-
-    # if the delimiter doesn't have an html representation we check
-    # if any of the items has.  If yes we do a coercion to Markup
-    if not hasattr(d, '__html__'):
-        value = list(value)
-        do_escape = False
-        for idx, item in enumerate(value):
-            if hasattr(item, '__html__'):
-                do_escape = True
-            else:
-                value[idx] = unicode(item)
-        if do_escape:
-            d = escape(d)
-        else:
-            d = unicode(d)
-        return d.join(value)
-
-    # no html involved, to normal joining
-    return soft_unicode(d).join(imap(soft_unicode, value))
-
-
-def do_center(value, width=80):
-    """Centers the value in a field of a given width."""
-    return unicode(value).center(width)
-
-
-@environmentfilter
-def do_first(environment, seq):
-    """Return the first item of a sequence."""
-    try:
-        return iter(seq).next()
-    except StopIteration:
-        return environment.undefined('No first item, sequence was empty.')
-
-
-@environmentfilter
-def do_last(environment, seq):
-    """Return the last item of a sequence."""
-    try:
-        return iter(reversed(seq)).next()
-    except StopIteration:
-        return environment.undefined('No last item, sequence was empty.')
-
-
-@environmentfilter
-def do_random(environment, seq):
-    """Return a random item from the sequence."""
-    try:
-        return choice(seq)
-    except IndexError:
-        return environment.undefined('No random item, sequence was empty.')
-
-
-def do_filesizeformat(value, binary=False):
-    """Format the value like a 'human-readable' file size (i.e. 13 KB,
-    4.1 MB, 102 bytes, etc).  Per default decimal prefixes are used (mega,
-    giga, etc.), if the second parameter is set to `True` the binary
-    prefixes are used (mebi, gibi).
-    """
-    bytes = float(value)
-    base = binary and 1024 or 1000
-    middle = binary and 'i' or ''
-    if bytes < base:
-        return "%d Byte%s" % (bytes, bytes != 1 and 's' or '')
-    elif bytes < base * base:
-        return "%.1f K%sB" % (bytes / base, middle)
-    elif bytes < base * base * base:
-        return "%.1f M%sB" % (bytes / (base * base), middle)
-    return "%.1f G%sB" % (bytes / (base * base * base), middle)
-
-
-def do_pprint(value, verbose=False):
-    """Pretty print a variable. Useful for debugging.
-
-    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
-    is truthy the output will be more verbose (this requires `pretty`)
-    """
-    return pformat(value, verbose=verbose)
-
-
-@evalcontextfilter
-def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
-    """Converts URLs in plain text into clickable links.
-
-    If you pass the filter an additional integer it will shorten the urls
-    to that number. Also a third argument exists that makes the urls
-    "nofollow":
-
-    .. sourcecode:: jinja
-
-        {{ mytext|urlize(40, true) }}
-            links are shortened to 40 chars and defined with rel="nofollow"
-    """
-    rv = urlize(value, trim_url_limit, nofollow)
-    if eval_ctx.autoescape:
-        rv = Markup(rv)
-    return rv
-
-
-def do_indent(s, width=4, indentfirst=False):
-    """Return a copy of the passed string, each line indented by
-    4 spaces. The first line is not indented. If you want to
-    change the number of spaces or indent the first line too
-    you can pass additional parameters to the filter:
-
-    .. sourcecode:: jinja
-
-        {{ mytext|indent(2, true) }}
-            indent by two spaces and indent the first line too.
-    """
-    indention = u' ' * width
-    rv = (u'\n' + indention).join(s.splitlines())
-    if indentfirst:
-        rv = indention + rv
-    return rv
-
-
-def do_truncate(s, length=255, killwords=False, end='...'):
-    """Return a truncated copy of the string. The length is specified
-    with the first parameter which defaults to ``255``. If the second
-    parameter is ``true`` the filter will cut the text at length. Otherwise
-    it will try to save the last word. If the text was in fact
-    truncated it will append an ellipsis sign (``"..."``). If you want a
-    different ellipsis sign than ``"..."`` you can specify it using the
-    third parameter.
-
-    .. sourcecode jinja::
-
-        {{ mytext|truncate(300, false, '&raquo;') }}
-            truncate mytext to 300 chars, don't split up words, use a
-            right pointing double arrow as ellipsis sign.
-    """
-    if len(s) <= length:
-        return s
-    elif killwords:
-        return s[:length] + end
-    words = s.split(' ')
-    result = []
-    m = 0
-    for word in words:
-        m += len(word) + 1
-        if m > length:
-            break
-        result.append(word)
-    result.append(end)
-    return u' '.join(result)
-
-
-def do_wordwrap(s, width=79, break_long_words=True):
-    """
-    Return a copy of the string passed to the filter wrapped after
-    ``79`` characters.  You can override this default using the first
-    parameter.  If you set the second parameter to `false` Jinja will not
-    split words apart if they are longer than `width`.
-    """
-    import textwrap
-    return u'\n'.join(textwrap.wrap(s, width=width, expand_tabs=False,
-                                   replace_whitespace=False,
-                                   break_long_words=break_long_words))
-
-
-def do_wordcount(s):
-    """Count the words in that string."""
-    return len(_word_re.findall(s))
-
-
-def do_int(value, default=0):
-    """Convert the value into an integer. If the
-    conversion doesn't work it will return ``0``. You can
-    override this default using the first parameter.
-    """
-    try:
-        return int(value)
-    except (TypeError, ValueError):
-        # this quirk is necessary so that "42.23"|int gives 42.
-        try:
-            return int(float(value))
-        except (TypeError, ValueError):
-            return default
-
-
-def do_float(value, default=0.0):
-    """Convert the value into a floating point number. If the
-    conversion doesn't work it will return ``0.0``. You can
-    override this default using the first parameter.
-    """
-    try:
-        return float(value)
-    except (TypeError, ValueError):
-        return default
-
-
-def do_format(value, *args, **kwargs):
-    """
-    Apply python string formatting on an object:
-
-    .. sourcecode:: jinja
-
-        {{ "%s - %s"|format("Hello?", "Foo!") }}
-            -> Hello? - Foo!
-    """
-    if args and kwargs:
-        raise FilterArgumentError('can\'t handle positional and keyword '
-                                  'arguments at the same time')
-    return soft_unicode(value) % (kwargs or args)
-
-
-def do_trim(value):
-    """Strip leading and trailing whitespace."""
-    return soft_unicode(value).strip()
-
-
-def do_striptags(value):
-    """Strip SGML/XML tags and replace adjacent whitespace by one space.
-    """
-    if hasattr(value, '__html__'):
-        value = value.__html__()
-    return Markup(unicode(value)).striptags()
-
-
-def do_slice(value, slices, fill_with=None):
-    """Slice an iterator and return a list of lists containing
-    those items. Useful if you want to create a div containing
-    three ul tags that represent columns:
-
-    .. sourcecode:: html+jinja
-
-        <div class="columwrapper">
-          {%- for column in items|slice(3) %}
-            <ul class="column-{{ loop.index }}">
-            {%- for item in column %}
-              <li>{{ item }}</li>
-            {%- endfor %}
-            </ul>
-          {%- endfor %}
-        </div>
-
-    If you pass it a second argument it's used to fill missing
-    values on the last iteration.
-    """
-    seq = list(value)
-    length = len(seq)
-    items_per_slice = length // slices
-    slices_with_extra = length % slices
-    offset = 0
-    for slice_number in xrange(slices):
-        start = offset + slice_number * items_per_slice
-        if slice_number < slices_with_extra:
-            offset += 1
-        end = offset + (slice_number + 1) * items_per_slice
-        tmp = seq[start:end]
-        if fill_with is not None and slice_number >= slices_with_extra:
-            tmp.append(fill_with)
-        yield tmp
-
-
-def do_batch(value, linecount, fill_with=None):
-    """
-    A filter that batches items. It works pretty much like `slice`
-    just the other way round. It returns a list of lists with the
-    given number of items. If you provide a second parameter this
-    is used to fill missing items. See this example:
-
-    .. sourcecode:: html+jinja
-
-        <table>
-        {%- for row in items|batch(3, '&nbsp;') %}
-          <tr>
-          {%- for column in row %}
-            <td>{{ column }}</td>
-          {%- endfor %}
-          </tr>
-        {%- endfor %}
-        </table>
-    """
-    result = []
-    tmp = []
-    for item in value:
-        if len(tmp) == linecount:
-            yield tmp
-            tmp = []
-        tmp.append(item)
-    if tmp:
-        if fill_with is not None and len(tmp) < linecount:
-            tmp += [fill_with] * (linecount - len(tmp))
-        yield tmp
-
-
-def do_round(value, precision=0, method='common'):
-    """Round the number to a given precision. The first
-    parameter specifies the precision (default is ``0``), the
-    second the rounding method:
-
-    - ``'common'`` rounds either up or down
-    - ``'ceil'`` always rounds up
-    - ``'floor'`` always rounds down
-
-    If you don't specify a method ``'common'`` is used.
-
-    .. sourcecode:: jinja
-
-        {{ 42.55|round }}
-            -> 43.0
-        {{ 42.55|round(1, 'floor') }}
-            -> 42.5
-
-    Note that even if rounded to 0 precision, a float is returned.  If
-    you need a real integer, pipe it through `int`:
-
-    .. sourcecode:: jinja
-
-        {{ 42.55|round|int }}
-            -> 43
-    """
-    if not method in ('common', 'ceil', 'floor'):
-        raise FilterArgumentError('method must be common, ceil or floor')
-    if method == 'common':
-        return round(value, precision)
-    func = getattr(math, method)
-    return func(value * (10 ** precision)) / (10 ** precision)
-
-
-@environmentfilter
-def do_groupby(environment, value, attribute):
-    """Group a sequence of objects by a common attribute.
-
-    If you for example have a list of dicts or objects that represent persons
-    with `gender`, `first_name` and `last_name` attributes and you want to
-    group all users by genders you can do something like the following
-    snippet:
-
-    .. sourcecode:: html+jinja
-
-        <ul>
-        {% for group in persons|groupby('gender') %}
-            <li>{{ group.grouper }}<ul>
-            {% for person in group.list %}
-                <li>{{ person.first_name }} {{ person.last_name }}</li>
-            {% endfor %}</ul></li>
-        {% endfor %}
-        </ul>
-
-    Additionally it's possible to use tuple unpacking for the grouper and
-    list:
-
-    .. sourcecode:: html+jinja
-
-        <ul>
-        {% for grouper, list in persons|groupby('gender') %}
-            ...
-        {% endfor %}
-        </ul>
-
-    As you can see the item we're grouping by is stored in the `grouper`
-    attribute and the `list` contains all the objects that have this grouper
-    in common.
-    """
-    expr = lambda x: environment.getitem(x, attribute)
-    return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
-
-
-class _GroupTuple(tuple):
-    __slots__ = ()
-    grouper = property(itemgetter(0))
-    list = property(itemgetter(1))
-
-    def __new__(cls, (key, value)):
-        return tuple.__new__(cls, (key, list(value)))
-
-
-def do_list(value):
-    """Convert the value into a list.  If it was a string the returned list
-    will be a list of characters.
-    """
-    return list(value)
-
-
-def do_mark_safe(value):
-    """Mark the value as safe which means that in an environment with automatic
-    escaping enabled this variable will not be escaped.
-    """
-    return Markup(value)
-
-
-def do_mark_unsafe(value):
-    """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
-    return unicode(value)
-
-
-def do_reverse(value):
-    """Reverse the object or return an iterator the iterates over it the other
-    way round.
-    """
-    if isinstance(value, basestring):
-        return value[::-1]
-    try:
-        return reversed(value)
-    except TypeError:
-        try:
-            rv = list(value)
-            rv.reverse()
-            return rv
-        except TypeError:
-            raise FilterArgumentError('argument must be iterable')
-
-
-@environmentfilter
-def do_attr(environment, obj, name):
-    """Get an attribute of an object.  ``foo|attr("bar")`` works like
-    ``foo["bar"]`` just that always an attribute is returned and items are not
-    looked up.
-
-    See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
-    """
-    try:
-        name = str(name)
-    except UnicodeError:
-        pass
-    else:
-        try:
-            value = getattr(obj, name)
-        except AttributeError:
-            pass
-        else:
-            if environment.sandboxed and not \
-               environment.is_safe_attribute(obj, name, value):
-                return environment.unsafe_undefined(obj, name)
-            return value
-    return environment.undefined(obj=obj, name=name)
-
-
-FILTERS = {
-    'attr':                 do_attr,
-    'replace':              do_replace,
-    'upper':                do_upper,
-    'lower':                do_lower,
-    'escape':               escape,
-    'e':                    escape,
-    'forceescape':          do_forceescape,
-    'capitalize':           do_capitalize,
-    'title':                do_title,
-    'default':              do_default,
-    'd':                    do_default,
-    'join':                 do_join,
-    'count':                len,
-    'dictsort':             do_dictsort,
-    'sort':                 do_sort,
-    'length':               len,
-    'reverse':              do_reverse,
-    'center':               do_center,
-    'indent':               do_indent,
-    'title':                do_title,
-    'capitalize':           do_capitalize,
-    'first':                do_first,
-    'last':                 do_last,
-    'random':               do_random,
-    'filesizeformat':       do_filesizeformat,
-    'pprint':               do_pprint,
-    'truncate':             do_truncate,
-    'wordwrap':             do_wordwrap,
-    'wordcount':            do_wordcount,
-    'int':                  do_int,
-    'float':                do_float,
-    'string':               soft_unicode,
-    'list':                 do_list,
-    'urlize':               do_urlize,
-    'format':               do_format,
-    'trim':                 do_trim,
-    'striptags':            do_striptags,
-    'slice':                do_slice,
-    'batch':                do_batch,
-    'sum':                  sum,
-    'abs':                  abs,
-    'round':                do_round,
-    'groupby':              do_groupby,
-    'safe':                 do_mark_safe,
-    'xmlattr':              do_xmlattr
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py
deleted file mode 100644
index 0c385c1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py
+++ /dev/null
@@ -1,681 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.lexer
-    ~~~~~~~~~~~~
-
-    This module implements a Jinja / Python combination lexer. The
-    `Lexer` class provided by this module is used to do some preprocessing
-    for Jinja.
-
-    On the one hand it filters out invalid operators like the bitshift
-    operators we don't allow in templates. On the other hand it separates
-    template code and python code in expressions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-from operator import itemgetter
-from collections import deque
-from ambari_jinja2.exceptions import TemplateSyntaxError
-from ambari_jinja2.utils import LRUCache, next
-
-
-# cache for the lexers. Exists in order to be able to have multiple
-# environments with the same lexer
-_lexer_cache = LRUCache(50)
-
-# static regular expressions
-whitespace_re = re.compile(r'\s+', re.U)
-string_re = re.compile(r"('([^'\\]*(?:\\.[^'\\]*)*)'"
-                       r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
-integer_re = re.compile(r'\d+')
-
-# we use the unicode identifier rule if this python version is able
-# to handle unicode identifiers, otherwise the standard ASCII one.
-try:
-    compile('föö', '<unknown>', 'eval')
-except SyntaxError:
-    name_re = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b')
-else:
-    from ambari_jinja2 import _stringdefs
-    name_re = re.compile(r'[%s][%s]*' % (_stringdefs.xid_start,
-                                         _stringdefs.xid_continue))
-
-float_re = re.compile(r'(?<!\.)\d+\.\d+')
-newline_re = re.compile(r'(\r\n|\r|\n)')
-
-# internal the tokens and keep references to them
-TOKEN_ADD = intern('add')
-TOKEN_ASSIGN = intern('assign')
-TOKEN_COLON = intern('colon')
-TOKEN_COMMA = intern('comma')
-TOKEN_DIV = intern('div')
-TOKEN_DOT = intern('dot')
-TOKEN_EQ = intern('eq')
-TOKEN_FLOORDIV = intern('floordiv')
-TOKEN_GT = intern('gt')
-TOKEN_GTEQ = intern('gteq')
-TOKEN_LBRACE = intern('lbrace')
-TOKEN_LBRACKET = intern('lbracket')
-TOKEN_LPAREN = intern('lparen')
-TOKEN_LT = intern('lt')
-TOKEN_LTEQ = intern('lteq')
-TOKEN_MOD = intern('mod')
-TOKEN_MUL = intern('mul')
-TOKEN_NE = intern('ne')
-TOKEN_PIPE = intern('pipe')
-TOKEN_POW = intern('pow')
-TOKEN_RBRACE = intern('rbrace')
-TOKEN_RBRACKET = intern('rbracket')
-TOKEN_RPAREN = intern('rparen')
-TOKEN_SEMICOLON = intern('semicolon')
-TOKEN_SUB = intern('sub')
-TOKEN_TILDE = intern('tilde')
-TOKEN_WHITESPACE = intern('whitespace')
-TOKEN_FLOAT = intern('float')
-TOKEN_INTEGER = intern('integer')
-TOKEN_NAME = intern('name')
-TOKEN_STRING = intern('string')
-TOKEN_OPERATOR = intern('operator')
-TOKEN_BLOCK_BEGIN = intern('block_begin')
-TOKEN_BLOCK_END = intern('block_end')
-TOKEN_VARIABLE_BEGIN = intern('variable_begin')
-TOKEN_VARIABLE_END = intern('variable_end')
-TOKEN_RAW_BEGIN = intern('raw_begin')
-TOKEN_RAW_END = intern('raw_end')
-TOKEN_COMMENT_BEGIN = intern('comment_begin')
-TOKEN_COMMENT_END = intern('comment_end')
-TOKEN_COMMENT = intern('comment')
-TOKEN_LINESTATEMENT_BEGIN = intern('linestatement_begin')
-TOKEN_LINESTATEMENT_END = intern('linestatement_end')
-TOKEN_LINECOMMENT_BEGIN = intern('linecomment_begin')
-TOKEN_LINECOMMENT_END = intern('linecomment_end')
-TOKEN_LINECOMMENT = intern('linecomment')
-TOKEN_DATA = intern('data')
-TOKEN_INITIAL = intern('initial')
-TOKEN_EOF = intern('eof')
-
-# bind operators to token types
-operators = {
-    '+':            TOKEN_ADD,
-    '-':            TOKEN_SUB,
-    '/':            TOKEN_DIV,
-    '//':           TOKEN_FLOORDIV,
-    '*':            TOKEN_MUL,
-    '%':            TOKEN_MOD,
-    '**':           TOKEN_POW,
-    '~':            TOKEN_TILDE,
-    '[':            TOKEN_LBRACKET,
-    ']':            TOKEN_RBRACKET,
-    '(':            TOKEN_LPAREN,
-    ')':            TOKEN_RPAREN,
-    '{':            TOKEN_LBRACE,
-    '}':            TOKEN_RBRACE,
-    '==':           TOKEN_EQ,
-    '!=':           TOKEN_NE,
-    '>':            TOKEN_GT,
-    '>=':           TOKEN_GTEQ,
-    '<':            TOKEN_LT,
-    '<=':           TOKEN_LTEQ,
-    '=':            TOKEN_ASSIGN,
-    '.':            TOKEN_DOT,
-    ':':            TOKEN_COLON,
-    '|':            TOKEN_PIPE,
-    ',':            TOKEN_COMMA,
-    ';':            TOKEN_SEMICOLON
-}
-
-reverse_operators = dict([(v, k) for k, v in operators.iteritems()])
-assert len(operators) == len(reverse_operators), 'operators dropped'
-operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
-                         sorted(operators, key=lambda x: -len(x))))
-
-ignored_tokens = frozenset([TOKEN_COMMENT_BEGIN, TOKEN_COMMENT,
-                            TOKEN_COMMENT_END, TOKEN_WHITESPACE,
-                            TOKEN_WHITESPACE, TOKEN_LINECOMMENT_BEGIN,
-                            TOKEN_LINECOMMENT_END, TOKEN_LINECOMMENT])
-ignore_if_empty = frozenset([TOKEN_WHITESPACE, TOKEN_DATA,
-                             TOKEN_COMMENT, TOKEN_LINECOMMENT])
-
-
-def _describe_token_type(token_type):
-    if token_type in reverse_operators:
-        return reverse_operators[token_type]
-    return {
-        TOKEN_COMMENT_BEGIN:        'begin of comment',
-        TOKEN_COMMENT_END:          'end of comment',
-        TOKEN_COMMENT:              'comment',
-        TOKEN_LINECOMMENT:          'comment',
-        TOKEN_BLOCK_BEGIN:          'begin of statement block',
-        TOKEN_BLOCK_END:            'end of statement block',
-        TOKEN_VARIABLE_BEGIN:       'begin of print statement',
-        TOKEN_VARIABLE_END:         'end of print statement',
-        TOKEN_LINESTATEMENT_BEGIN:  'begin of line statement',
-        TOKEN_LINESTATEMENT_END:    'end of line statement',
-        TOKEN_DATA:                 'template data / text',
-        TOKEN_EOF:                  'end of template'
-    }.get(token_type, token_type)
-
-
-def describe_token(token):
-    """Returns a description of the token."""
-    if token.type == 'name':
-        return token.value
-    return _describe_token_type(token.type)
-
-
-def describe_token_expr(expr):
-    """Like `describe_token` but for token expressions."""
-    if ':' in expr:
-        type, value = expr.split(':', 1)
-        if type == 'name':
-            return value
-    else:
-        type = expr
-    return _describe_token_type(type)
-
-
-def count_newlines(value):
-    """Count the number of newline characters in the string.  This is
-    useful for extensions that filter a stream.
-    """
-    return len(newline_re.findall(value))
-
-
-def compile_rules(environment):
-    """Compiles all the rules from the environment into a list of rules."""
-    e = re.escape
-    rules = [
-        (len(environment.comment_start_string), 'comment',
-         e(environment.comment_start_string)),
-        (len(environment.block_start_string), 'block',
-         e(environment.block_start_string)),
-        (len(environment.variable_start_string), 'variable',
-         e(environment.variable_start_string))
-    ]
-
-    if environment.line_statement_prefix is not None:
-        rules.append((len(environment.line_statement_prefix), 'linestatement',
-                      r'^\s*' + e(environment.line_statement_prefix)))
-    if environment.line_comment_prefix is not None:
-        rules.append((len(environment.line_comment_prefix), 'linecomment',
-                      r'(?:^|(?<=\S))[^\S\r\n]*' +
-                      e(environment.line_comment_prefix)))
-
-    return [x[1:] for x in sorted(rules, reverse=True)]
-
-
-class Failure(object):
-    """Class that raises a `TemplateSyntaxError` if called.
-    Used by the `Lexer` to specify known errors.
-    """
-
-    def __init__(self, message, cls=TemplateSyntaxError):
-        self.message = message
-        self.error_class = cls
-
-    def __call__(self, lineno, filename):
-        raise self.error_class(self.message, lineno, filename)
-
-
-class Token(tuple):
-    """Token class."""
-    __slots__ = ()
-    lineno, type, value = (property(itemgetter(x)) for x in range(3))
-
-    def __new__(cls, lineno, type, value):
-        return tuple.__new__(cls, (lineno, intern(str(type)), value))
-
-    def __str__(self):
-        if self.type in reverse_operators:
-            return reverse_operators[self.type]
-        elif self.type == 'name':
-            return self.value
-        return self.type
-
-    def test(self, expr):
-        """Test a token against a token expression.  This can either be a
-        token type or ``'token_type:token_value'``.  This can only test
-        against string values and types.
-        """
-        # here we do a regular string equality check as test_any is usually
-        # passed an iterable of not interned strings.
-        if self.type == expr:
-            return True
-        elif ':' in expr:
-            return expr.split(':', 1) == [self.type, self.value]
-        return False
-
-    def test_any(self, *iterable):
-        """Test against multiple token expressions."""
-        for expr in iterable:
-            if self.test(expr):
-                return True
-        return False
-
-    def __repr__(self):
-        return 'Token(%r, %r, %r)' % (
-            self.lineno,
-            self.type,
-            self.value
-        )
-
-
-class TokenStreamIterator(object):
-    """The iterator for tokenstreams.  Iterate over the stream
-    until the eof token is reached.
-    """
-
-    def __init__(self, stream):
-        self.stream = stream
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        token = self.stream.current
-        if token.type is TOKEN_EOF:
-            self.stream.close()
-            raise StopIteration()
-        next(self.stream)
-        return token
-
-
-class TokenStream(object):
-    """A token stream is an iterable that yields :class:`Token`\s.  The
-    parser however does not iterate over it but calls :meth:`next` to go
-    one token ahead.  The current active token is stored as :attr:`current`.
-    """
-
-    def __init__(self, generator, name, filename):
-        self._next = iter(generator).next
-        self._pushed = deque()
-        self.name = name
-        self.filename = filename
-        self.closed = False
-        self.current = Token(1, TOKEN_INITIAL, '')
-        next(self)
-
-    def __iter__(self):
-        return TokenStreamIterator(self)
-
-    def __nonzero__(self):
-        return bool(self._pushed) or self.current.type is not TOKEN_EOF
-
-    eos = property(lambda x: not x, doc="Are we at the end of the stream?")
-
-    def push(self, token):
-        """Push a token back to the stream."""
-        self._pushed.append(token)
-
-    def look(self):
-        """Look at the next token."""
-        old_token = next(self)
-        result = self.current
-        self.push(result)
-        self.current = old_token
-        return result
-
-    def skip(self, n=1):
-        """Got n tokens ahead."""
-        for x in xrange(n):
-            next(self)
-
-    def next_if(self, expr):
-        """Perform the token test and return the token if it matched.
-        Otherwise the return value is `None`.
-        """
-        if self.current.test(expr):
-            return next(self)
-
-    def skip_if(self, expr):
-        """Like :meth:`next_if` but only returns `True` or `False`."""
-        return self.next_if(expr) is not None
-
-    def next(self):
-        """Go one token ahead and return the old one"""
-        rv = self.current
-        if self._pushed:
-            self.current = self._pushed.popleft()
-        elif self.current.type is not TOKEN_EOF:
-            try:
-                self.current = self._next()
-            except StopIteration:
-                self.close()
-        return rv
-
-    def close(self):
-        """Close the stream."""
-        self.current = Token(self.current.lineno, TOKEN_EOF, '')
-        self._next = None
-        self.closed = True
-
-    def expect(self, expr):
-        """Expect a given token type and return it.  This accepts the same
-        argument as :meth:`ambari_jinja2.lexer.Token.test`.
-        """
-        if not self.current.test(expr):
-            expr = describe_token_expr(expr)
-            if self.current.type is TOKEN_EOF:
-                raise TemplateSyntaxError('unexpected end of template, '
-                                          'expected %r.' % expr,
-                                          self.current.lineno,
-                                          self.name, self.filename)
-            raise TemplateSyntaxError("expected token %r, got %r" %
-                                      (expr, describe_token(self.current)),
-                                      self.current.lineno,
-                                      self.name, self.filename)
-        try:
-            return self.current
-        finally:
-            next(self)
-
-
-def get_lexer(environment):
-    """Return a lexer which is probably cached."""
-    key = (environment.block_start_string,
-           environment.block_end_string,
-           environment.variable_start_string,
-           environment.variable_end_string,
-           environment.comment_start_string,
-           environment.comment_end_string,
-           environment.line_statement_prefix,
-           environment.line_comment_prefix,
-           environment.trim_blocks,
-           environment.newline_sequence)
-    lexer = _lexer_cache.get(key)
-    if lexer is None:
-        lexer = Lexer(environment)
-        _lexer_cache[key] = lexer
-    return lexer
-
-
-class Lexer(object):
-    """Class that implements a lexer for a given environment. Automatically
-    created by the environment class, usually you don't have to do that.
-
-    Note that the lexer is not automatically bound to an environment.
-    Multiple environments can share the same lexer.
-    """
-
-    def __init__(self, environment):
-        # shortcuts
-        c = lambda x: re.compile(x, re.M | re.S)
-        e = re.escape
-
-        # lexing rules for tags
-        tag_rules = [
-            (whitespace_re, TOKEN_WHITESPACE, None),
-            (float_re, TOKEN_FLOAT, None),
-            (integer_re, TOKEN_INTEGER, None),
-            (name_re, TOKEN_NAME, None),
-            (string_re, TOKEN_STRING, None),
-            (operator_re, TOKEN_OPERATOR, None)
-        ]
-
-        # assamble the root lexing rule. because "|" is ungreedy
-        # we have to sort by length so that the lexer continues working
-        # as expected when we have parsing rules like <% for block and
-        # <%= for variables. (if someone wants asp like syntax)
-        # variables are just part of the rules if variable processing
-        # is required.
-        root_tag_rules = compile_rules(environment)
-
-        # block suffix if trimming is enabled
-        block_suffix_re = environment.trim_blocks and '\\n?' or ''
-
-        self.newline_sequence = environment.newline_sequence
-
-        # global lexing rules
-        self.rules = {
-            'root': [
-                # directives
-                (c('(.*?)(?:%s)' % '|'.join(
-                    [r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
-                        e(environment.block_start_string),
-                        e(environment.block_start_string),
-                        e(environment.block_end_string),
-                        e(environment.block_end_string)
-                    )] + [
-                        r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, r)
-                        for n, r in root_tag_rules
-                    ])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
-                # data
-                (c('.+'), TOKEN_DATA, None)
-            ],
-            # comments
-            TOKEN_COMMENT_BEGIN: [
-                (c(r'(.*?)((?:\-%s\s*|%s)%s)' % (
-                    e(environment.comment_end_string),
-                    e(environment.comment_end_string),
-                    block_suffix_re
-                )), (TOKEN_COMMENT, TOKEN_COMMENT_END), '#pop'),
-                (c('(.)'), (Failure('Missing end of comment tag'),), None)
-            ],
-            # blocks
-            TOKEN_BLOCK_BEGIN: [
-                (c('(?:\-%s\s*|%s)%s' % (
-                    e(environment.block_end_string),
-                    e(environment.block_end_string),
-                    block_suffix_re
-                )), TOKEN_BLOCK_END, '#pop'),
-            ] + tag_rules,
-            # variables
-            TOKEN_VARIABLE_BEGIN: [
-                (c('\-%s\s*|%s' % (
-                    e(environment.variable_end_string),
-                    e(environment.variable_end_string)
-                )), TOKEN_VARIABLE_END, '#pop')
-            ] + tag_rules,
-            # raw block
-            TOKEN_RAW_BEGIN: [
-                (c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
-                    e(environment.block_start_string),
-                    e(environment.block_start_string),
-                    e(environment.block_end_string),
-                    e(environment.block_end_string),
-                    block_suffix_re
-                )), (TOKEN_DATA, TOKEN_RAW_END), '#pop'),
-                (c('(.)'), (Failure('Missing end of raw directive'),), None)
-            ],
-            # line statements
-            TOKEN_LINESTATEMENT_BEGIN: [
-                (c(r'\s*(\n|$)'), TOKEN_LINESTATEMENT_END, '#pop')
-            ] + tag_rules,
-            # line comments
-            TOKEN_LINECOMMENT_BEGIN: [
-                (c(r'(.*?)()(?=\n|$)'), (TOKEN_LINECOMMENT,
-                 TOKEN_LINECOMMENT_END), '#pop')
-            ]
-        }
-
-    def _normalize_newlines(self, value):
-        """Called for strings and template data to normlize it to unicode."""
-        return newline_re.sub(self.newline_sequence, value)
-
-    def tokenize(self, source, name=None, filename=None, state=None):
-        """Calls tokeniter + tokenize and wraps it in a token stream.
-        """
-        stream = self.tokeniter(source, name, filename, state)
-        return TokenStream(self.wrap(stream, name, filename), name, filename)
-
-    def wrap(self, stream, name=None, filename=None):
-        """This is called with the stream as returned by `tokenize` and wraps
-        every token in a :class:`Token` and converts the value.
-        """
-        for lineno, token, value in stream:
-            if token in ignored_tokens:
-                continue
-            elif token == 'linestatement_begin':
-                token = 'block_begin'
-            elif token == 'linestatement_end':
-                token = 'block_end'
-            # we are not interested in those tokens in the parser
-            elif token in ('raw_begin', 'raw_end'):
-                continue
-            elif token == 'data':
-                value = self._normalize_newlines(value)
-            elif token == 'keyword':
-                token = value
-            elif token == 'name':
-                value = str(value)
-            elif token == 'string':
-                # try to unescape string
-                try:
-                    value = self._normalize_newlines(value[1:-1]) \
-                        .encode('ascii', 'backslashreplace') \
-                        .decode('unicode-escape')
-                except Exception, e:
-                    msg = str(e).split(':')[-1].strip()
-                    raise TemplateSyntaxError(msg, lineno, name, filename)
-                # if we can express it as bytestring (ascii only)
-                # we do that for support of semi broken APIs
-                # as datetime.datetime.strftime.  On python 3 this
-                # call becomes a noop thanks to 2to3
-                try:
-                    value = str(value)
-                except UnicodeError:
-                    pass
-            elif token == 'integer':
-                value = int(value)
-            elif token == 'float':
-                value = float(value)
-            elif token == 'operator':
-                token = operators[value]
-            yield Token(lineno, token, value)
-
-    def tokeniter(self, source, name, filename=None, state=None):
-        """This method tokenizes the text and returns the tokens in a
-        generator.  Use this method if you just want to tokenize a template.
-        """
-        source = '\n'.join(unicode(source).splitlines())
-        pos = 0
-        lineno = 1
-        stack = ['root']
-        if state is not None and state != 'root':
-            assert state in ('variable', 'block'), 'invalid state'
-            stack.append(state + '_begin')
-        else:
-            state = 'root'
-        statetokens = self.rules[stack[-1]]
-        source_length = len(source)
-
-        balancing_stack = []
-
-        while 1:
-            # tokenizer loop
-            for regex, tokens, new_state in statetokens:
-                m = regex.match(source, pos)
-                # if no match we try again with the next rule
-                if m is None:
-                    continue
-
-                # we only match blocks and variables if brances / parentheses
-                # are balanced. continue parsing with the lower rule which
-                # is the operator rule. do this only if the end tags look
-                # like operators
-                if balancing_stack and \
-                   tokens in ('variable_end', 'block_end',
-                              'linestatement_end'):
-                    continue
-
-                # tuples support more options
-                if isinstance(tokens, tuple):
-                    for idx, token in enumerate(tokens):
-                        # failure group
-                        if token.__class__ is Failure:
-                            raise token(lineno, filename)
-                        # bygroup is a bit more complex, in that case we
-                        # yield for the current token the first named
-                        # group that matched
-                        elif token == '#bygroup':
-                            for key, value in m.groupdict().iteritems():
-                                if value is not None:
-                                    yield lineno, key, value
-                                    lineno += value.count('\n')
-                                    break
-                            else:
-                                raise RuntimeError('%r wanted to resolve '
-                                                   'the token dynamically'
-                                                   ' but no group matched'
-                                                   % regex)
-                        # normal group
-                        else:
-                            data = m.group(idx + 1)
-                            if data or token not in ignore_if_empty:
-                                yield lineno, token, data
-                            lineno += data.count('\n')
-
-                # strings as token just are yielded as it.
-                else:
-                    data = m.group()
-                    # update brace/parentheses balance
-                    if tokens == 'operator':
-                        if data == '{':
-                            balancing_stack.append('}')
-                        elif data == '(':
-                            balancing_stack.append(')')
-                        elif data == '[':
-                            balancing_stack.append(']')
-                        elif data in ('}', ')', ']'):
-                            if not balancing_stack:
-                                raise TemplateSyntaxError('unexpected \'%s\'' %
-                                                          data, lineno, name,
-                                                          filename)
-                            expected_op = balancing_stack.pop()
-                            if expected_op != data:
-                                raise TemplateSyntaxError('unexpected \'%s\', '
-                                                          'expected \'%s\'' %
-                                                          (data, expected_op),
-                                                          lineno, name,
-                                                          filename)
-                    # yield items
-                    if data or tokens not in ignore_if_empty:
-                        yield lineno, tokens, data
-                    lineno += data.count('\n')
-
-                # fetch new position into new variable so that we can check
-                # if there is a internal parsing error which would result
-                # in an infinite loop
-                pos2 = m.end()
-
-                # handle state changes
-                if new_state is not None:
-                    # remove the uppermost state
-                    if new_state == '#pop':
-                        stack.pop()
-                    # resolve the new state by group checking
-                    elif new_state == '#bygroup':
-                        for key, value in m.groupdict().iteritems():
-                            if value is not None:
-                                stack.append(key)
-                                break
-                        else:
-                            raise RuntimeError('%r wanted to resolve the '
-                                               'new state dynamically but'
-                                               ' no group matched' %
-                                               regex)
-                    # direct state name given
-                    else:
-                        stack.append(new_state)
-                    statetokens = self.rules[stack[-1]]
-                # we are still at the same position and no stack change.
-                # this means a loop without break condition, avoid that and
-                # raise error
-                elif pos2 == pos:
-                    raise RuntimeError('%r yielded empty string without '
-                                       'stack change' % regex)
-                # publish new function and start again
-                pos = pos2
-                break
-            # if loop terminated without break we havn't found a single match
-            # either we are at the end of the file or we have a problem
-            else:
-                # end of text
-                if pos >= source_length:
-                    return
-                # something went wrong
-                raise TemplateSyntaxError('unexpected char %r at %d' %
-                                          (source[pos], pos), lineno,
-                                          name, filename)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py
deleted file mode 100644
index b25be08..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py
+++ /dev/null
@@ -1,449 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.loaders
-    ~~~~~~~~~~~~~~
-
-    Jinja loader classes.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import weakref
-from types import ModuleType
-from os import path
-try:
-    from hashlib import sha1
-except ImportError:
-    from sha import new as sha1
-from ambari_jinja2.exceptions import TemplateNotFound
-from ambari_jinja2.utils import LRUCache, open_if_exists, internalcode
-
-
-def split_template_path(template):
-    """Split a path into segments and perform a sanity check.  If it detects
-    '..' in the path it will raise a `TemplateNotFound` error.
-    """
-    pieces = []
-    for piece in template.split('/'):
-        if path.sep in piece \
-           or (path.altsep and path.altsep in piece) or \
-           piece == path.pardir:
-            raise TemplateNotFound(template)
-        elif piece and piece != '.':
-            pieces.append(piece)
-    return pieces
-
-
-class BaseLoader(object):
-    """Baseclass for all loaders.  Subclass this and override `get_source` to
-    implement a custom loading mechanism.  The environment provides a
-    `get_template` method that calls the loader's `load` method to get the
-    :class:`Template` object.
-
-    A very basic example for a loader that looks up templates on the file
-    system could look like this::
-
-        from ambari_jinja2 import BaseLoader, TemplateNotFound
-        from os.path import join, exists, getmtime
-
-        class MyLoader(BaseLoader):
-
-            def __init__(self, path):
-                self.path = path
-
-            def get_source(self, environment, template):
-                path = join(self.path, template)
-                if not exists(path):
-                    raise TemplateNotFound(template)
-                mtime = getmtime(path)
-                with file(path) as f:
-                    source = f.read().decode('utf-8')
-                return source, path, lambda: mtime == getmtime(path)
-    """
-
-    #: if set to `False` it indicates that the loader cannot provide access
-    #: to the source of templates.
-    #:
-    #: .. versionadded:: 2.4
-    has_source_access = True
-
-    def get_source(self, environment, template):
-        """Get the template source, filename and reload helper for a template.
-        It's passed the environment and template name and has to return a
-        tuple in the form ``(source, filename, uptodate)`` or raise a
-        `TemplateNotFound` error if it can't locate the template.
-
-        The source part of the returned tuple must be the source of the
-        template as unicode string or a ASCII bytestring.  The filename should
-        be the name of the file on the filesystem if it was loaded from there,
-        otherwise `None`.  The filename is used by python for the tracebacks
-        if no loader extension is used.
-
-        The last item in the tuple is the `uptodate` function.  If auto
-        reloading is enabled it's always called to check if the template
-        changed.  No arguments are passed so the function must store the
-        old state somewhere (for example in a closure).  If it returns `False`
-        the template will be reloaded.
-        """
-        if not self.has_source_access:
-            raise RuntimeError('%s cannot provide access to the source' %
-                               self.__class__.__name__)
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        """Iterates over all templates.  If the loader does not support that
-        it should raise a :exc:`TypeError` which is the default behavior.
-        """
-        raise TypeError('this loader cannot iterate over all templates')
-
-    @internalcode
-    def load(self, environment, name, globals=None):
-        """Loads a template.  This method looks up the template in the cache
-        or loads one by calling :meth:`get_source`.  Subclasses should not
-        override this method as loaders working on collections of other
-        loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)
-        will not call this method but `get_source` directly.
-        """
-        code = None
-        if globals is None:
-            globals = {}
-
-        # first we try to get the source for this template together
-        # with the filename and the uptodate function.
-        source, filename, uptodate = self.get_source(environment, name)
-
-        # try to load the code from the bytecode cache if there is a
-        # bytecode cache configured.
-        bcc = environment.bytecode_cache
-        if bcc is not None:
-            bucket = bcc.get_bucket(environment, name, filename, source)
-            code = bucket.code
-
-        # if we don't have code so far (not cached, no longer up to
-        # date) etc. we compile the template
-        if code is None:
-            code = environment.compile(source, name, filename)
-
-        # if the bytecode cache is available and the bucket doesn't
-        # have a code so far, we give the bucket the new code and put
-        # it back to the bytecode cache.
-        if bcc is not None and bucket.code is None:
-            bucket.code = code
-            bcc.set_bucket(bucket)
-
-        return environment.template_class.from_code(environment, code,
-                                                    globals, uptodate)
-
-
-class FileSystemLoader(BaseLoader):
-    """Loads templates from the file system.  This loader can find templates
-    in folders on the file system and is the preferred way to load them.
-
-    The loader takes the path to the templates as string, or if multiple
-    locations are wanted a list of them which is then looked up in the
-    given order:
-
-    >>> loader = FileSystemLoader('/path/to/templates')
-    >>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
-
-    Per default the template encoding is ``'utf-8'`` which can be changed
-    by setting the `encoding` parameter to something else.
-    """
-
-    def __init__(self, searchpath, encoding='utf-8'):
-        if isinstance(searchpath, basestring):
-            searchpath = [searchpath]
-        self.searchpath = list(searchpath)
-        self.encoding = encoding
-
-    def get_source(self, environment, template):
-        pieces = split_template_path(template)
-        for searchpath in self.searchpath:
-            filename = path.join(searchpath, *pieces)
-            f = open_if_exists(filename)
-            if f is None:
-                continue
-            try:
-                contents = f.read().decode(self.encoding)
-            finally:
-                f.close()
-
-            mtime = path.getmtime(filename)
-            def uptodate():
-                try:
-                    return path.getmtime(filename) == mtime
-                except OSError:
-                    return False
-            return contents, filename, uptodate
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        found = set()
-        for searchpath in self.searchpath:
-            for dirpath, dirnames, filenames in os.walk(searchpath):
-                for filename in filenames:
-                    template = os.path.join(dirpath, filename) \
-                        [len(searchpath):].strip(os.path.sep) \
-                                          .replace(os.path.sep, '/')
-                    if template[:2] == './':
-                        template = template[2:]
-                    if template not in found:
-                        found.add(template)
-        return sorted(found)
-
-
-class PackageLoader(BaseLoader):
-    """Load templates from python eggs or packages.  It is constructed with
-    the name of the python package and the path to the templates in that
-    package::
-
-        loader = PackageLoader('mypackage', 'views')
-
-    If the package path is not given, ``'templates'`` is assumed.
-
-    Per default the template encoding is ``'utf-8'`` which can be changed
-    by setting the `encoding` parameter to something else.  Due to the nature
-    of eggs it's only possible to reload templates if the package was loaded
-    from the file system and not a zip file.
-    """
-
-    def __init__(self, package_name, package_path='templates',
-                 encoding='utf-8'):
-        from pkg_resources import DefaultProvider, ResourceManager, \
-                                  get_provider
-        provider = get_provider(package_name)
-        self.encoding = encoding
-        self.manager = ResourceManager()
-        self.filesystem_bound = isinstance(provider, DefaultProvider)
-        self.provider = provider
-        self.package_path = package_path
-
-    def get_source(self, environment, template):
-        pieces = split_template_path(template)
-        p = '/'.join((self.package_path,) + tuple(pieces))
-        if not self.provider.has_resource(p):
-            raise TemplateNotFound(template)
-
-        filename = uptodate = None
-        if self.filesystem_bound:
-            filename = self.provider.get_resource_filename(self.manager, p)
-            mtime = path.getmtime(filename)
-            def uptodate():
-                try:
-                    return path.getmtime(filename) == mtime
-                except OSError:
-                    return False
-
-        source = self.provider.get_resource_string(self.manager, p)
-        return source.decode(self.encoding), filename, uptodate
-
-    def list_templates(self):
-        path = self.package_path
-        if path[:2] == './':
-            path = path[2:]
-        elif path == '.':
-            path = ''
-        offset = len(path)
-        results = []
-        def _walk(path):
-            for filename in self.provider.resource_listdir(path):
-                fullname = path + '/' + filename
-                if self.provider.resource_isdir(fullname):
-                    for item in _walk(fullname):
-                        results.append(item)
-                else:
-                    results.append(fullname[offset:].lstrip('/'))
-        _walk(path)
-        results.sort()
-        return results
-
-
-class DictLoader(BaseLoader):
-    """Loads a template from a python dict.  It's passed a dict of unicode
-    strings bound to template names.  This loader is useful for unittesting:
-
-    >>> loader = DictLoader({'index.html': 'source here'})
-
-    Because auto reloading is rarely useful this is disabled per default.
-    """
-
-    def __init__(self, mapping):
-        self.mapping = mapping
-
-    def get_source(self, environment, template):
-        if template in self.mapping:
-            source = self.mapping[template]
-            return source, None, lambda: source != self.mapping.get(template)
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        return sorted(self.mapping)
-
-
-class FunctionLoader(BaseLoader):
-    """A loader that is passed a function which does the loading.  The
-    function becomes the name of the template passed and has to return either
-    an unicode string with the template source, a tuple in the form ``(source,
-    filename, uptodatefunc)`` or `None` if the template does not exist.
-
-    >>> def load_template(name):
-    ...     if name == 'index.html':
-    ...         return '...'
-    ...
-    >>> loader = FunctionLoader(load_template)
-
-    The `uptodatefunc` is a function that is called if autoreload is enabled
-    and has to return `True` if the template is still up to date.  For more
-    details have a look at :meth:`BaseLoader.get_source` which has the same
-    return value.
-    """
-
-    def __init__(self, load_func):
-        self.load_func = load_func
-
-    def get_source(self, environment, template):
-        rv = self.load_func(template)
-        if rv is None:
-            raise TemplateNotFound(template)
-        elif isinstance(rv, basestring):
-            return rv, None, None
-        return rv
-
-
-class PrefixLoader(BaseLoader):
-    """A loader that is passed a dict of loaders where each loader is bound
-    to a prefix.  The prefix is delimited from the template by a slash per
-    default, which can be changed by setting the `delimiter` argument to
-    something else::
-
-        loader = PrefixLoader({
-            'app1':     PackageLoader('mypackage.app1'),
-            'app2':     PackageLoader('mypackage.app2')
-        })
-
-    By loading ``'app1/index.html'`` the file from the app1 package is loaded,
-    by loading ``'app2/index.html'`` the file from the second.
-    """
-
-    def __init__(self, mapping, delimiter='/'):
-        self.mapping = mapping
-        self.delimiter = delimiter
-
-    def get_source(self, environment, template):
-        try:
-            prefix, name = template.split(self.delimiter, 1)
-            loader = self.mapping[prefix]
-        except (ValueError, KeyError):
-            raise TemplateNotFound(template)
-        try:
-            return loader.get_source(environment, name)
-        except TemplateNotFound:
-            # re-raise the exception with the correct fileame here.
-            # (the one that includes the prefix)
-            raise TemplateNotFound(template)
-
-    def list_templates(self):
-        result = []
-        for prefix, loader in self.mapping.iteritems():
-            for template in loader.list_templates():
-                result.append(prefix + self.delimiter + template)
-        return result
-
-
-class ChoiceLoader(BaseLoader):
-    """This loader works like the `PrefixLoader` just that no prefix is
-    specified.  If a template could not be found by one loader the next one
-    is tried.
-
-    >>> loader = ChoiceLoader([
-    ...     FileSystemLoader('/path/to/user/templates'),
-    ...     FileSystemLoader('/path/to/system/templates')
-    ... ])
-
-    This is useful if you want to allow users to override builtin templates
-    from a different location.
-    """
-
-    def __init__(self, loaders):
-        self.loaders = loaders
-
-    def get_source(self, environment, template):
-        for loader in self.loaders:
-            try:
-                return loader.get_source(environment, template)
-            except TemplateNotFound:
-                pass
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        found = set()
-        for loader in self.loaders:
-            found.update(loader.list_templates())
-        return sorted(found)
-
-
-class _TemplateModule(ModuleType):
-    """Like a normal module but with support for weak references"""
-
-
-class ModuleLoader(BaseLoader):
-    """This loader loads templates from precompiled templates.
-
-    Example usage:
-
-    >>> loader = ChoiceLoader([
-    ...     ModuleLoader('/path/to/compiled/templates'),
-    ...     FileSystemLoader('/path/to/templates')
-    ... ])
-    """
-
-    has_source_access = False
-
-    def __init__(self, path):
-        package_name = '_ambari_jinja2_module_templates_%x' % id(self)
-
-        # create a fake module that looks for the templates in the
-        # path given.
-        mod = _TemplateModule(package_name)
-        if isinstance(path, basestring):
-            path = [path]
-        else:
-            path = list(path)
-        mod.__path__ = path
-
-        sys.modules[package_name] = weakref.proxy(mod,
-            lambda x: sys.modules.pop(package_name, None))
-
-        # the only strong reference, the sys.modules entry is weak
-        # so that the garbage collector can remove it once the
-        # loader that created it goes out of business.
-        self.module = mod
-        self.package_name = package_name
-
-    @staticmethod
-    def get_template_key(name):
-        return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest()
-
-    @staticmethod
-    def get_module_filename(name):
-        return ModuleLoader.get_template_key(name) + '.py'
-
-    @internalcode
-    def load(self, environment, name, globals=None):
-        key = self.get_template_key(name)
-        module = '%s.%s' % (self.package_name, key)
-        mod = getattr(self.module, module, None)
-        if mod is None:
-            try:
-                mod = __import__(module, None, None, ['root'])
-            except ImportError:
-                raise TemplateNotFound(name)
-
-            # remove the entry from sys.modules, we only want the attribute
-            # on the module object we have stored on the loader.
-            sys.modules.pop(module, None)
-
-        return environment.template_class.from_module_dict(
-            environment, mod.__dict__, globals)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py
deleted file mode 100644
index afe7771..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.meta
-    ~~~~~~~~~~~
-
-    This module implements various functions that exposes information about
-    templates that might be interesting for various kinds of applications.
-
-    :copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-from ambari_jinja2 import nodes
-from ambari_jinja2.compiler import CodeGenerator
-
-
-class TrackingCodeGenerator(CodeGenerator):
-    """We abuse the code generator for introspection."""
-
-    def __init__(self, environment):
-        CodeGenerator.__init__(self, environment, '<introspection>',
-                               '<introspection>')
-        self.undeclared_identifiers = set()
-
-    def write(self, x):
-        """Don't write."""
-
-    def pull_locals(self, frame):
-        """Remember all undeclared identifiers."""
-        self.undeclared_identifiers.update(frame.identifiers.undeclared)
-
-
-def find_undeclared_variables(ast):
-    """Returns a set of all variables in the AST that will be looked up from
-    the context at runtime.  Because at compile time it's not known which
-    variables will be used depending on the path the execution takes at
-    runtime, all variables are returned.
-
-    >>> from ambari_jinja2 import Environment, meta
-    >>> env = Environment()
-    >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
-    >>> meta.find_undeclared_variables(ast)
-    set(['bar'])
-
-    .. admonition:: Implementation
-
-       Internally the code generator is used for finding undeclared variables.
-       This is good to know because the code generator might raise a
-       :exc:`TemplateAssertionError` during compilation and as a matter of
-       fact this function can currently raise that exception as well.
-    """
-    codegen = TrackingCodeGenerator(ast.environment)
-    codegen.visit(ast)
-    return codegen.undeclared_identifiers
-
-
-def find_referenced_templates(ast):
-    """Finds all the referenced templates from the AST.  This will return an
-    iterator over all the hardcoded template extensions, inclusions and
-    imports.  If dynamic inheritance or inclusion is used, `None` will be
-    yielded.
-
-    >>> from ambari_jinja2 import Environment, meta
-    >>> env = Environment()
-    >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
-    >>> list(meta.find_referenced_templates(ast))
-    ['layout.html', None]
-
-    This function is useful for dependency tracking.  For example if you want
-    to rebuild parts of the website after a layout template has changed.
-    """
-    for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import,
-                              nodes.Include)):
-        if not isinstance(node.template, nodes.Const):
-            # a tuple with some non consts in there
-            if isinstance(node.template, (nodes.Tuple, nodes.List)):
-                for template_name in node.template.items:
-                    # something const, only yield the strings and ignore
-                    # non-string consts that really just make no sense
-                    if isinstance(template_name, nodes.Const):
-                        if isinstance(template_name.value, basestring):
-                            yield template_name.value
-                    # something dynamic in there
-                    else:
-                        yield None
-            # something dynamic we don't know about here
-            else:
-                yield None
-            continue
-        # constant is a basestring, direct template name
-        if isinstance(node.template.value, basestring):
-            yield node.template.value
-        # a tuple or list (latter *should* not happen) made of consts,
-        # yield the consts that are strings.  We could warn here for
-        # non string values
-        elif isinstance(node, nodes.Include) and \
-             isinstance(node.template.value, (tuple, list)):
-            for template_name in node.template.value:
-                if isinstance(template_name, basestring):
-                    yield template_name
-        # something else we don't care about, we could warn here
-        else:
-            yield None


[41/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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/658360a5/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)


[52/59] [abbrv] git commit: AMBARI-7151. Create a HDP 2.2.1 Stack that extends HDP 2.0.6 stack. (aonishuk)

Posted by nc...@apache.org.
AMBARI-7151. Create a HDP 2.2.1 Stack that extends HDP 2.0.6 stack. (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/91e0c66d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/91e0c66d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/91e0c66d

Branch: refs/heads/branch-alerts-dev
Commit: 91e0c66db25e43e06fac07f9111d3e20df60865c
Parents: 658360a
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Thu Sep 4 19:30:49 2014 +0300
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Thu Sep 4 19:30:49 2014 +0300

----------------------------------------------------------------------
 .../stacks/HDP/2.1/services/SQOOP/metainfo.xml  |  4 -
 .../resources/stacks/HDP/2.2.1/metainfo.xml     | 23 ++++++
 .../stacks/HDP/2.2.1/repos/repoinfo.xml         | 67 +++++++++++++++
 .../stacks/HDP/2.2.1/role_command_order.json    | 85 ++++++++++++++++++++
 .../HDP/2.2.1/services/FALCON/metainfo.xml      | 26 ++++++
 .../HDP/2.2.1/services/FLUME/metainfo.xml       | 26 ++++++
 .../HDP/2.2.1/services/HBASE/metainfo.xml       | 26 ++++++
 .../stacks/HDP/2.2.1/services/HDFS/metainfo.xml | 27 +++++++
 .../stacks/HDP/2.2.1/services/HIVE/metainfo.xml | 31 +++++++
 .../HDP/2.2.1/services/OOZIE/metainfo.xml       | 26 ++++++
 .../stacks/HDP/2.2.1/services/PIG/metainfo.xml  | 26 ++++++
 .../HDP/2.2.1/services/SQOOP/metainfo.xml       | 26 ++++++
 .../HDP/2.2.1/services/STORM/metainfo.xml       | 27 +++++++
 .../stacks/HDP/2.2.1/services/TEZ/metainfo.xml  | 26 ++++++
 .../HDP/2.2.1/services/WEBHCAT/metainfo.xml     | 26 ++++++
 .../stacks/HDP/2.2.1/services/YARN/metainfo.xml | 31 +++++++
 .../HDP/2.2.1/services/ZOOKEEPER/metainfo.xml   | 26 ++++++
 17 files changed, 525 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.1/services/SQOOP/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.1/services/SQOOP/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.1/services/SQOOP/metainfo.xml
index f981ae6..a50b1e5 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.1/services/SQOOP/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.1/services/SQOOP/metainfo.xml
@@ -25,9 +25,5 @@
       </comment>
       <version>1.4.4.2.1</version>
     </service>
-    
-    <configuration-dependencies>
-      <config-type>sqoop-env</config-type>
-    </configuration-dependencies>
   </services>
 </metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/metainfo.xml
new file mode 100644
index 0000000..0be6cb6
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/metainfo.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+    <versions>
+	  <active>true</active>
+    </versions>
+    <extends>2.1</extends>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/repos/repoinfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/repos/repoinfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/repos/repoinfo.xml
new file mode 100644
index 0000000..c7c3e36
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/repos/repoinfo.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<reposinfo>
+  <os type="redhat6">
+    <repo>
+      <baseurl>http://dev.hortonworks.com.s3.amazonaws.com/HDP/centos5/2.x/updates/2.2.0.0</baseurl>
+      <repoid>HDP-2.2.1</repoid>
+      <reponame>HDP</reponame>
+    </repo>
+    <repo>
+      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-UTILS-1.1.0.19/repos/centos6</baseurl>
+      <repoid>HDP-UTILS-1.1.0.19</repoid>
+      <reponame>HDP-UTILS</reponame>
+    </repo>
+  </os>
+  <os type="redhat5">
+    <repo>
+      <baseurl>http://dev.hortonworks.com.s3.amazonaws.com/HDP/centos6/2.x/updates/2.2.0.0</baseurl>
+      <repoid>HDP-2.2.1</repoid>
+      <reponame>HDP</reponame>
+    </repo>
+    <repo>
+      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-UTILS-1.1.0.19/repos/centos5</baseurl>
+      <repoid>HDP-UTILS-1.1.0.19</repoid>
+      <reponame>HDP-UTILS</reponame>
+    </repo>
+  </os>
+  <os type="suse11">
+    <repo>
+      <baseurl>http://dev.hortonworks.com.s3.amazonaws.com/HDP/sles11sp1/2.x/updates/2.2.0.0</baseurl>
+      <repoid>HDP-2.2.1</repoid>
+      <reponame>HDP</reponame>
+    </repo>
+    <repo>
+      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-UTILS-1.1.0.19/repos/suse11sp3</baseurl>
+      <repoid>HDP-UTILS-1.1.0.19</repoid>
+      <reponame>HDP-UTILS</reponame>
+    </repo>
+  </os>
+  <os type="ubuntu12">
+    <repo>
+      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP/ubuntu12/2.x/updates/2.2.0.0</baseurl>
+      <repoid>HDP-2.2.1</repoid>
+      <reponame>HDP</reponame>
+    </repo>
+    <repo>
+      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-UTILS-1.1.0.19/repos/ubuntu12</baseurl>
+      <repoid>HDP-UTILS-1.1.0.19</repoid>
+      <reponame>HDP-UTILS</reponame>
+    </repo>
+  </os>
+</reposinfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/role_command_order.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/role_command_order.json b/ambari-server/src/main/resources/stacks/HDP/2.2.1/role_command_order.json
new file mode 100644
index 0000000..b97a31a
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/role_command_order.json
@@ -0,0 +1,85 @@
+{
+  "_comment" : "Record format:",
+  "_comment" : "blockedRole-blockedCommand: [blockerRole1-blockerCommand1, blockerRole2-blockerCommand2, ...]",
+  "general_deps" : {
+    "_comment" : "dependencies for all cases",
+    "NAGIOS_SERVER-INSTALL" : ["HIVE_CLIENT-INSTALL", "HCAT-INSTALL",
+        "MAPREDUCE_CLIENT-INSTALL", "OOZIE_CLIENT-INSTALL"],
+    "NIMBUS-START" : ["ZOOKEEPER_SERVER-START"],
+    "SUPERVISOR-START" : ["NIMBUS-START"],
+    "STORM_UI_SERVER-START" : ["NIMBUS-START"],
+    "DRPC_SERVER-START" : ["NIMBUS-START"],
+    "STORM_REST_API-START" : ["NIMBUS-START", "STORM_UI_SERVER-START", "SUPERVISOR-START", "DRPC_SERVER-START"],
+    "HBASE_MASTER-START": ["ZOOKEEPER_SERVER-START"],
+    "HBASE_REGIONSERVER-START": ["HBASE_MASTER-START"],
+    "OOZIE_SERVER-START": ["NODEMANAGER-START", "RESOURCEMANAGER-START"],
+    "WEBHCAT_SERVER-START": ["NODEMANAGER-START", "HIVE_SERVER-START"],
+    "HIVE_METASTORE-START": ["MYSQL_SERVER-START"],
+    "HIVE_SERVER-START": ["NODEMANAGER-START", "MYSQL_SERVER-START"],
+    "HUE_SERVER-START": ["HIVE_SERVER-START", "HCAT-START", "OOZIE_SERVER-START"],
+    "FLUME_HANDLER-START": ["OOZIE_SERVER-START"],
+    "NAGIOS_SERVER-START": ["HBASE_MASTER-START", "HBASE_REGIONSERVER-START",
+        "GANGLIA_SERVER-START", "GANGLIA_MONITOR-START", "HCAT-START",
+        "HIVE_SERVER-START", "HIVE_METASTORE-START", "HUE_SERVER-START",
+        "NODEMANAGER-START", "RESOURCEMANAGER-START", "ZOOKEEPER_SERVER-START",
+        "MYSQL_SERVER-START", "OOZIE_SERVER-START", "PIG-START", "SQOOP-START",
+        "WEBHCAT_SERVER-START", "FLUME_HANDLER-START"],
+    "MAPREDUCE_SERVICE_CHECK-SERVICE_CHECK": ["NODEMANAGER-START", "RESOURCEMANAGER-START"],
+    "OOZIE_SERVICE_CHECK-SERVICE_CHECK": ["OOZIE_SERVER-START"],
+    "WEBHCAT_SERVICE_CHECK-SERVICE_CHECK": ["WEBHCAT_SERVER-START"],
+    "HBASE_SERVICE_CHECK-SERVICE_CHECK": ["HBASE_MASTER-START", "HBASE_REGIONSERVER-START"],
+    "HIVE_SERVICE_CHECK-SERVICE_CHECK": ["HIVE_SERVER-START", "HIVE_METASTORE-START"],
+    "HCAT_SERVICE_CHECK-SERVICE_CHECK": ["HIVE_SERVER-START"],
+    "PIG_SERVICE_CHECK-SERVICE_CHECK": ["NODEMANAGER-START", "RESOURCEMANAGER-START"],
+    "SQOOP_SERVICE_CHECK-SERVICE_CHECK": ["NODEMANAGER-START", "RESOURCEMANAGER-START"],
+    "ZOOKEEPER_SERVICE_CHECK-SERVICE_CHECK": ["ZOOKEEPER_SERVER-START"],
+    "ZOOKEEPER_QUORUM_SERVICE_CHECK-SERVICE_CHECK": ["ZOOKEEPER_SERVER-START"],
+    "STORM_SERVICE_CHECK-SERVICE_CHECK": ["NIMBUS-START", "SUPERVISOR-START", "STORM_UI_SERVER-START",
+        "DRPC_SERVER-START"],
+    "ZOOKEEPER_SERVER-STOP" : ["HBASE_MASTER-STOP", "HBASE_REGIONSERVER-STOP"],
+    "HBASE_MASTER-STOP": ["HBASE_REGIONSERVER-STOP"],
+    "NIMBUS-STOP" : ["SUPERVISOR-STOP", "STORM_UI_SERVER-STOP", "DRPC_SERVER-STOP"]
+  },
+  "_comment" : "GLUSTERFS-specific dependencies",
+  "optional_glusterfs": {
+    "HBASE_MASTER-START": ["PEERSTATUS-START"],
+    "GLUSTERFS_SERVICE_CHECK-SERVICE_CHECK": ["PEERSTATUS-START"]
+  },
+  "_comment" : "Dependencies that are used when GLUSTERFS is not present in cluster",
+  "optional_no_glusterfs": {
+    "SECONDARY_NAMENODE-START": ["NAMENODE-START"],
+    "RESOURCEMANAGER-START": ["NAMENODE-START", "DATANODE-START"],
+    "NODEMANAGER-START": ["NAMENODE-START", "DATANODE-START", "RESOURCEMANAGER-START"],
+    "HISTORYSERVER-START": ["NAMENODE-START", "DATANODE-START"],
+    "HBASE_MASTER-START": ["NAMENODE-START", "DATANODE-START"],
+    "APP_TIMELINE_SERVER-START": ["NAMENODE-START", "DATANODE-START"],
+    "FALCON_SERVER-START": ["NAMENODE-START", "DATANODE-START"],
+    "FALCON_SERVICE_CHECK-SERVICE_CHECK": ["FALCON_SERVER-START"],
+    "HIVE_SERVER-START": ["DATANODE-START"],
+    "WEBHCAT_SERVER-START": ["DATANODE-START"],
+    "NAGIOS_SERVER-START": ["NAMENODE-START", "SECONDARY_NAMENODE-START",
+        "DATANODE-START", "RESOURCEMANAGER-START", "NODEMANAGER-START", "HISTORYSERVER-START"],
+    "HDFS_SERVICE_CHECK-SERVICE_CHECK": ["NAMENODE-START", "DATANODE-START",
+        "SECONDARY_NAMENODE-START"],
+    "MAPREDUCE2_SERVICE_CHECK-SERVICE_CHECK": ["NODEMANAGER-START",
+        "RESOURCEMANAGER-START", "HISTORYSERVER-START", "YARN_SERVICE_CHECK-SERVICE_CHECK"],
+    "YARN_SERVICE_CHECK-SERVICE_CHECK": ["NODEMANAGER-START", "RESOURCEMANAGER-START"],
+    "RESOURCEMANAGER_SERVICE_CHECK-SERVICE_CHECK": ["RESOURCEMANAGER-START"],
+    "PIG_SERVICE_CHECK-SERVICE_CHECK": ["RESOURCEMANAGER-START", "NODEMANAGER-START"],
+    "NAMENODE-STOP": ["RESOURCEMANAGER-STOP", "NODEMANAGER-STOP",
+        "HISTORYSERVER-STOP", "HBASE_MASTER-STOP", "FALCON_SERVER-STOP"],
+    "DATANODE-STOP": ["RESOURCEMANAGER-STOP", "NODEMANAGER-STOP",
+        "HISTORYSERVER-STOP", "HBASE_MASTER-STOP", "FALCON_SERVER-STOP"]
+  },
+  "_comment" : "Dependencies that are used in HA NameNode cluster",
+  "namenode_optional_ha": {
+    "NAMENODE-START": ["ZKFC-START", "JOURNALNODE-START", "ZOOKEEPER_SERVER-START"],
+    "ZKFC-START": ["ZOOKEEPER_SERVER-START"],
+    "NAGIOS_SERVER-START": ["ZKFC-START", "JOURNALNODE-START"]
+  },
+  "_comment" : "Dependencies that are used in ResourceManager HA cluster",
+  "resourcemanager_optional_ha" : {
+    "RESOURCEMANAGER-START": ["ZOOKEEPER_SERVER-START"]
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FALCON/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FALCON/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FALCON/metainfo.xml
new file mode 100644
index 0000000..8eadd09
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FALCON/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>FALCON</name>
+      <version>0.6.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FLUME/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FLUME/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FLUME/metainfo.xml
new file mode 100644
index 0000000..9db692d
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/FLUME/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>FLUME</name>
+      <version>1.5.0.1.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HBASE/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HBASE/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HBASE/metainfo.xml
new file mode 100644
index 0000000..7a6116a
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HBASE/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>HBASE</name>
+      <version>0.98.4.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HDFS/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HDFS/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HDFS/metainfo.xml
new file mode 100644
index 0000000..76348f3
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HDFS/metainfo.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>HDFS</name>
+      <comment>Apache Hadoop Distributed File System</comment>
+      <version>2.6.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HIVE/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HIVE/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HIVE/metainfo.xml
new file mode 100644
index 0000000..686d596
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/HIVE/metainfo.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>HIVE</name>
+      <comment>Data warehouse system for ad-hoc queries &amp; analysis of large datasets and table &amp; storage management service</comment>
+      <version>0.14.0.2.2</version>
+    </service>
+    <service>
+      <name>HCATALOG</name>
+      <version>0.14.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/OOZIE/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/OOZIE/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/OOZIE/metainfo.xml
new file mode 100644
index 0000000..4ee93f7
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/OOZIE/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>OOZIE</name>
+      <version>4.1.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/PIG/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/PIG/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/PIG/metainfo.xml
new file mode 100644
index 0000000..3b5a522
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/PIG/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>PIG</name>
+      <version>0.14.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/SQOOP/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/SQOOP/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/SQOOP/metainfo.xml
new file mode 100644
index 0000000..9d61ae8
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/SQOOP/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>SQOOP</name>
+      <version>1.4.5.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/STORM/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/STORM/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/STORM/metainfo.xml
new file mode 100644
index 0000000..37e7d99
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/STORM/metainfo.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>STORM</name>
+      <version>0.9.3.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/TEZ/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/TEZ/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/TEZ/metainfo.xml
new file mode 100644
index 0000000..3eb5189
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/TEZ/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>TEZ</name>
+      <version>0.6.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/WEBHCAT/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/WEBHCAT/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/WEBHCAT/metainfo.xml
new file mode 100644
index 0000000..a5222aa
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/WEBHCAT/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>WEBHCAT</name>
+      <version>0.14.0.2.2</version>
+    </service>
+  </services>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/YARN/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/YARN/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/YARN/metainfo.xml
new file mode 100644
index 0000000..3f17168
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/YARN/metainfo.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>YARN</name>
+      <version>2.6.0.2.2</version>
+    </service>
+  </services>
+  <service>
+    <name>MAPREDUCE2</name>
+    <version>2.6.0.2.2</version>
+  </service>
+</metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/91e0c66d/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/ZOOKEEPER/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/ZOOKEEPER/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/ZOOKEEPER/metainfo.xml
new file mode 100644
index 0000000..9728d96
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2.1/services/ZOOKEEPER/metainfo.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>ZOOKEEPER</name>
+      <version>3.4.5.2.2</version>
+    </service>
+  </services>
+</metainfo>


[14/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py
deleted file mode 100644
index fd0ea68..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from lib2to3 import fixer_base, pytree
-from lib2to3.fixer_util import Name, BlankLine, Name, Attr, ArgList
-
-
-class FixBrokenReraising(fixer_base.BaseFix):
-    PATTERN = """
-    raise_stmt< 'raise' any ',' val=any ',' tb=any >
-    """
-
-    # run before the broken 2to3 checker with the same goal
-    # tries to rewrite it with a rule that does not work out for jinja
-    run_order = 1
-
-    def transform(self, node, results):
-        tb = results['tb'].clone()
-        tb.prefix = ''
-        with_tb = Attr(results['val'].clone(), Name('with_traceback')) + \
-                  [ArgList([tb])]
-        new = pytree.Node(self.syms.simple_stmt, [Name("raise")] + with_tb)
-        new.prefix = node.prefix
-        return new

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py
deleted file mode 100644
index 5d35e50..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from lib2to3 import fixer_base
-from lib2to3.fixer_util import Name, BlankLine
-
-
-# whyever this is necessary..
-
-class FixXrange2(fixer_base.BaseFix):
-    PATTERN = "'xrange'"
-
-    def transform(self, node, results):
-        node.replace(Name('range', prefix=node.prefix))

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/Makefile b/ambari-common/src/main/python/ambari_jinja2/docs/Makefile
deleted file mode 100644
index 5e24ec1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/Makefile
+++ /dev/null
@@ -1,75 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
-
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
-
-help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  html      to make standalone HTML files"
-	@echo "  pickle    to make pickle files"
-	@echo "  json      to make JSON files"
-	@echo "  htmlhelp  to make HTML files and a HTML help project"
-	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  changes   to make an overview over all changed/added/deprecated items"
-	@echo "  linkcheck to check all external links for integrity"
-
-clean:
-	-rm -rf _build/*
-
-html:
-	mkdir -p _build/html _build/doctrees
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
-	@echo
-	@echo "Build finished. The HTML pages are in _build/html."
-
-pickle:
-	mkdir -p _build/pickle _build/doctrees
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files"
-
-json:
-	mkdir -p _build/json _build/doctrees
-	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
-	@echo
-	@echo "Build finished; now you can process the json files"
-
-web: pickle
-
-htmlhelp:
-	mkdir -p _build/htmlhelp _build/doctrees
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in _build/htmlhelp."
-
-latex:
-	mkdir -p _build/latex _build/doctrees
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in _build/latex."
-	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
-	      "run these through (pdf)latex."
-
-changes:
-	mkdir -p _build/changes _build/doctrees
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
-	@echo
-	@echo "The overview file is in _build/changes."
-
-linkcheck:
-	mkdir -p _build/linkcheck _build/doctrees
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in _build/linkcheck/output.txt."

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js b/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js
deleted file mode 100644
index 1c04218..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js
+++ /dev/null
@@ -1,26 +0,0 @@
-$(function() {
-
-  var
-    toc = $('#toc').show(),
-    items = $('#toc > ul').hide();
-
-  $('#toc h3')
-    .click(function() {
-      if (items.is(':visible')) {
-        items.animate({
-          height:     'hide',
-          opacity:    'hide'
-        }, 300, function() {
-          toc.removeClass('expandedtoc');
-        });
-      }
-      else {
-        items.animate({
-          height:     'show',
-          opacity:    'show'
-        }, 400);
-        toc.addClass('expandedtoc');
-      }
-    });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css b/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css
deleted file mode 100644
index fb633d8..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css
+++ /dev/null
@@ -1,5 +0,0 @@
-div.header, div.relnav, #toc { display: none; }
-#contentwrapper { padding: 0; margin: 0; border: none; }
-body { color: black; background-color: white; }
-div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
-div.footer a { text-decoration: none; }

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css b/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css
deleted file mode 100644
index a1c4d59..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css
+++ /dev/null
@@ -1,390 +0,0 @@
-body {
-    background-color: #222;
-    margin: 0;
-    padding: 0;
-    font-family: 'Georgia', serif;
-    font-size: 15px;
-    color: #eee;
-}
-
-div.footer {
-    border-top: 1px solid #111;
-    padding: 8px;
-    font-size: 11px;
-    text-align: center;
-    letter-spacing: 0.5px;
-}
-
-div.footer a {
-    color: #eee;
-}
-
-div.header {
-    margin: 0 -15px 0 -15px;
-    background: url(headerbg.png) repeat-x;
-    border-top: 6px solid #D20000;
-}
-
-div.relnav {
-    border-bottom: 1px solid #111;
-    background: url(navigation.png);
-    margin: 0 -15px 0 -15px;
-    padding: 2px 20px 0 28px;
-    line-height: 25px;
-    color: #aaa;
-    font-size: 12px;
-    text-align: center;
-}
-
-div.relnav a {
-    color: #eee;
-    font-weight: bold;
-    text-decoration: none;
-}
-
-div.relnav a:hover {
-    text-decoration: underline;
-}
-
-#content {
-    background-color: white;
-    color: #111;
-    border-bottom: 1px solid black;
-    background: url(watermark.png) center 0;
-    padding: 0 15px 0 15px;
-    margin: 0;
-}
-
-h1 {
-    margin: 0;
-    padding: 15px 0 0 0;
-}
-
-h1.heading {
-    margin: 0;
-    padding: 0;
-    height: 80px;
-}
-
-h1.heading:hover {
-    background: #222;
-}
-
-h1.heading a {
-    background: url(jinjabanner.png) no-repeat center 0;
-    display: block;
-    width: 100%;
-    height: 80px;
-}
-
-h1.heading a:focus {
-    -moz-outline: none;
-    outline: none;
-}
-
-h1.heading span {
-    display: none;
-}
-
-#jinjalogo {
-    background-image: url(jinjalogo.png);
-    background-repeat: no-repeat;
-    width: 400px;
-    height: 160px;
-}
-
-#contentwrapper {
-    max-width: 680px;
-    padding: 0 18px 20px 18px;
-    margin: 0 auto 0 auto;
-    border-right: 1px solid #eee;
-    border-left: 1px solid #eee;
-    background: url(watermark_blur.png) center -114px;
-}
-
-#contentwrapper h2,
-#contentwrapper h2 a {
-    color: #222;
-    font-size: 24px;
-    margin: 20px 0 0 0;
-}
-
-#contentwrapper h3,
-#contentwrapper h3 a {
-    color: #b41717;
-    font-size: 20px;
-    margin: 20px 0 0 0;
-}
-
-table.docutils {
-    border-collapse: collapse;
-    border: 2px solid #aaa;
-    margin: 0.5em 1.5em 0.5em 1.5em;
-}
-
-table.docutils td {
-    padding: 2px;
-    border: 1px solid #ddd;
-}
-
-p, li, dd, dt, blockquote {
-    color: #333;
-}
-
-blockquote {
-    margin: 10px 0 10px 20px;
-}
-
-p {
-    line-height: 20px;
-    margin-bottom: 0;
-    margin-top: 10px;
-}
-
-hr {
-    border-top: 1px solid #ccc;
-    border-bottom: 0;
-    border-right: 0;
-    border-left: 0;
-    margin-bottom: 10px;
-    margin-top: 20px;
-}
-
-dl {
-    margin-left: 10px;
-}
-
-li, dt {
-    margin-top: 5px;
-}
-
-dt {
-    font-weight: bold;
-    color: #000;
-}
-
-dd {
-    margin-top: 10px;
-    line-height: 20px;
-}
-
-th {
-    text-align: left;
-    padding: 3px;
-    background-color: #f2f2f2;
-}
-
-a {
-    color: #b41717;
-}
-
-a:hover {
-    color: #444;
-}
-
-pre {
-    background: #ededed url(metal.png);
-    border-top: 1px solid #ccc;
-    border-bottom: 1px solid #ccc;
-    padding: 5px;
-    font-size: 13px;
-    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
-}
-
-tt {
-    font-size: 13px;
-    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
-    color: black;
-    padding: 1px 2px 1px 2px;
-    background-color: #fafafa;
-    border-bottom: 1px solid #eee;
-}
-
-a.reference:hover tt {
-    border-bottom-color: #aaa;
-}
-
-cite {
-    /* abusing <cite>, it's generated by ReST for `x` */
-    font-size: 13px;
-    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
-    font-weight: bold;
-    font-style: normal;
-}
-
-div.admonition {
-    margin: 10px 0 10px 0;
-    padding: 10px 10px 10px 60px;
-    border: 1px solid #ccc;
-}
-
-div.admonition p.admonition-title {
-    background-color: #b41717;
-    color: white;
-    margin: -10px -10px 10px -60px;
-    padding: 4px 10px 4px 10px;
-    font-weight: bold;
-    font-size: 15px;
-}
-
-div.admonition p.admonition-title a {
-    color: white!important;
-}
-
-div.admonition-note {
-    background: url(note.png) no-repeat 10px 40px;
-}
-
-div.admonition-implementation {
-    background: url(implementation.png) no-repeat 10px 40px;
-}
-
-a.headerlink {
-    color: #B4B4B4!important;
-    font-size: 0.8em;
-    padding: 0 4px 0 4px;
-    text-decoration: none!important;
-    visibility: hidden;
-}
-
-h1:hover > a.headerlink,
-h2:hover > a.headerlink,
-h3:hover > a.headerlink,
-h4:hover > a.headerlink,
-h5:hover > a.headerlink,
-h6:hover > a.headerlink,
-dt:hover > a.headerlink,
-dt:hover > a.headerlink {
-    visibility: visible;
-}
-
-a.headerlink:hover {
-    background-color: #B4B4B4;
-    color: #F0F0F0!important;
-}
-
-table.indextable {
-    width: 100%;
-}
-
-table.indextable td {
-    vertical-align: top;
-    width: 50%;
-}
-
-table.indextable dl dd {
-    font-size: 11px;
-}
-
-table.indextable dl dd a {
-    color: #000;
-}
-
-dl.function dt,
-dl.class dt,
-dl.exception dt,
-dl.method dt,
-dl.attribute dt {
-    font-weight: normal;
-}
-
-dt .descname {
-    font-weight: bold;
-    margin-right: 4px;
-}
-
-dt .descname, dt .descclassname {
-    padding: 0;
-    background: transparent;
-    border-bottom: 1px solid #111;
-}
-
-dt .descclassname {
-    margin-left: 2px;
-}
-
-dl dt big {
-    font-size: 100%;
-}
-
-ul.search {
-    margin: 10px 0 0 30px;
-    padding: 0;
-}
-
-ul.search li {
-    margin: 10px 0 0 0;
-    padding: 0;
-}
-
-ul.search div.context {
-    font-size: 12px;
-    padding: 4px 0 0 20px;
-    color: #888;
-}
-
-span.highlight {
-    background-color: #eee;
-    border: 1px solid #ccc;
-}
-
-#toc {
-    margin: 0 -17px 0 -17px;
-    display: none;
-}
-
-#toc h3 {
-    float: right;
-    margin: 5px 5px 0 0;
-    padding: 0;
-    font-size: 12px;
-    color: #777;
-}
-
-#toc h3:hover {
-    color: #333;
-    cursor: pointer;
-}
-
-.expandedtoc {
-    background: #222 url(darkmetal.png);
-    border-bottom: 1px solid #111;
-    outline-bottom: 1px solid #000;
-    padding: 5px;
-}
-
-.expandedtoc h3 {
-    color: #aaa;
-    margin: 0!important;
-}
-
-.expandedtoc h3:hover {
-    color: white!important;
-}
-
-#tod h3:hover {
-    color: white;
-}
-
-#toc a {
-    color: #ddd;
-    text-decoration: none;
-}
-
-#toc a:hover {
-    color: white;
-    text-decoration: underline;
-}
-
-#toc ul {
-    margin: 5px 0 12px 17px;
-    padding: 0 7px 0 7px;
-}
-
-#toc ul ul {
-    margin-bottom: 0;
-}
-
-#toc ul li {
-    margin: 2px 0 0 0;
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html
deleted file mode 100644
index 9add6e9..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html
+++ /dev/null
@@ -1,36 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Index' %}
-{% block body %}
-
-  <h1 id="index">Index</h1>
-
-  {% for key, dummy in genindexentries -%}
-  <a href="#{{ key }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %}
-  {%- endfor %}
-  <hr>
-
-  {% for key, entries in genindexentries %}
-    <h2 id="{{ key }}">{{ key }}</h2>
-    <table class="indextable"><tr>
-    {%- for column in entries|slice(2) if column %}
-      <td><dl>
-      {%- for entryname, (links, subitems) in column %}
-        <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
-          {% for link in links[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor %}
-          {%- else %}{{ entryname|e }}{% endif %}</dt>
-        {%- if subitems %}
-        <dd><dl>
-          {%- for subentryname, subentrylinks in subitems %}
-          <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
-          {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor -%}
-          </dt>
-          {%- endfor %}
-        </dl></dd>
-        {%- endif -%}
-      {%- endfor %}
-      </dl></td>
-    {%- endfor %}
-    </tr></table>
-  {% endfor %}
-
-{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html
deleted file mode 100644
index f682f90..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-  <head>
-    <title>Jinja2 Documentation</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}" type="text/css">
-    <link rel="stylesheet" href="{{ pathto('_static/print.css', 1) }}" type="text/css" media="print">
-    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css">
-    {%- if builder != 'htmlhelp' %}
-    <script type="text/javascript">
-      var DOCUMENTATION_OPTIONS = {
-        URL_ROOT:   '{{ pathto("", 1) }}',
-        VERSION:    '{{ release }}'
-      };
-    </script>
-    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/jinja.js', 1) }}"></script>
-    {%- endif %}
-    {%- if use_opensearch and builder != 'htmlhelp' %}
-    <link rel="search" type="application/opensearchdescription+xml"
-          title="Search within {{ docstitle }}"
-          href="{{ pathto('_static/opensearch.xml', 1) }}">
-    {%- endif %}
-    {%- if hasdoc('about') %}
-    <link rel="author" title="About these documents" href="{{ pathto('about') }}">
-    {%- endif %}
-    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}">
-    <link rel="index" title="Global index" href="{{ pathto('genindex') }}">
-    <link rel="search" title="Search" href="{{ pathto('search') }}">
-    {%- if hasdoc('copyright') %}
-    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}">
-    {%- endif %}
-    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}">
-    {%- if parents %}
-    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}">
-    {%- endif %}
-    {%- if next %}
-    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}">
-    {%- endif %}
-    {%- if prev %}
-    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}">
-    {%- endif %}
-    {% block extrahead %}{% endblock %}
-  </head>
-  <body>
-    <div id="content">
-      <div class="header">
-        <h1 class="heading"><a href="{{ pathto('index') }}"
-          title="back to the documentation overview"><span>Jinja</span></a></h1>
-      </div>
-      <div class="relnav">
-        {%- if prev %}
-        <a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
-        {%- endif %}
-        <a href="{{ pathto(current_page_name) if current_page_name else '#' }}">{{ title }}</a>
-        {%- if next %}
-        | <a href="{{ next.link|e }}">{{ next.title }} &raquo;</a>
-        {%- endif %}
-      </div>
-      <div id="contentwrapper">
-        {%- if display_toc %}
-        <div id="toc">
-          <h3>Table Of Contents</h3>
-          {{ toc }}
-        </div>
-        {%- endif %}
-        {% block body %}{% endblock %}
-      </div>
-    </div>
-    <div class="footer">
-      © Copyright 2010 by the <a href="http://pocoo.org/">Pocoo Team</a>,
-      documentation generated by <a href="http://sphinx.pocoo.org/">Sphinx</a>
-    </div>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml
deleted file mode 100644
index 9f2fa42..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
-  <ShortName>{{ project }}</ShortName>
-  <Description>Search {{ docstitle }}</Description>
-  <InputEncoding>utf-8</InputEncoding>
-  <Url type="text/html" method="get"
-       template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&amp;check_keywords=yes&amp;area=default"/>
-  <LongName>{{ docstitle }}</LongName>
-</OpenSearchDescription>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html
deleted file mode 100644
index ee6cad3..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html
+++ /dev/null
@@ -1,4 +0,0 @@
-{% extends 'layout.html' %}
-{% block body %}
-  {{ body }}
-{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html
deleted file mode 100644
index 0c942b7..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html
+++ /dev/null
@@ -1,35 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Search' %}
-{% block extrahead %}
-    <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
-{% endblock %}
-{% block body %}
-  <h1 id="search-documentation">Search</h1>
-  <p>
-    From here you can search these documents. Enter your search
-    words into the box below and click "search". Note that the search
-    function will automatically search for all of the words. Pages
-    containing less words won't appear in the result list.
-  </p>
-  <form action="" method="get"><p>
-    <input type="text" name="q" value="">
-    <input type="submit" value="search">
-  </p></form>
-  {% if search_performed %}
-    <h2>Search Results</h2>
-    {% if not search_results %}
-      <p>Your search did not match any results.</p>
-    {% endif %}
-  {% endif %}
-  <div id="search-results">
-  {% if search_results %}
-    <ul>
-    {% for href, caption, context in search_results %}
-      <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
-        <div class="context">{{ context|e }}</div>
-      </li>
-    {% endfor %}
-    </ul>
-  {% endif %}
-  </div>
-{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/api.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/api.rst b/ambari-common/src/main/python/ambari_jinja2/docs/api.rst
deleted file mode 100644
index 92da04a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/api.rst
+++ /dev/null
@@ -1,787 +0,0 @@
-API
-===
-
-.. module:: ambari_jinja2
-    :synopsis: public Jinja2 API
-
-This document describes the API to Jinja2 and not the template language.  It
-will be most useful as reference to those implementing the template interface
-to the application and not those who are creating Jinja2 templates.
-
-Basics
-------
-
-Jinja2 uses a central object called the template :class:`Environment`.
-Instances of this class are used to store the configuration, global objects
-and are used to load templates from the file system or other locations.
-Even if you are creating templates from strings by using the constructor of
-:class:`Template` class, an environment is created automatically for you,
-albeit a shared one.
-
-Most applications will create one :class:`Environment` object on application
-initialization and use that to load templates.  In some cases it's however
-useful to have multiple environments side by side, if different configurations
-are in use.
-
-The simplest way to configure Jinja2 to load templates for your application
-looks roughly like this::
-
-    from ambari_jinja2 import Environment, PackageLoader
-    env = Environment(loader=PackageLoader('yourapplication', 'templates'))
-
-This will create a template environment with the default settings and a
-loader that looks up the templates in the `templates` folder inside the
-`yourapplication` python package.  Different loaders are available
-and you can also write your own if you want to load templates from a
-database or other resources.
-
-To load a template from this environment you just have to call the
-:meth:`get_template` method which then returns the loaded :class:`Template`::
-
-    template = env.get_template('mytemplate.html')
-
-To render it with some variables, just call the :meth:`render` method::
-
-    print template.render(the='variables', go='here')
-
-Using a template loader rather then passing strings to :class:`Template`
-or :meth:`Environment.from_string` has multiple advantages.  Besides being
-a lot easier to use it also enables template inheritance.
-
-
-Unicode
--------
-
-Jinja2 is using Unicode internally which means that you have to pass Unicode
-objects to the render function or bytestrings that only consist of ASCII
-characters.  Additionally newlines are normalized to one end of line
-sequence which is per default UNIX style (``\n``).
-
-Python 2.x supports two ways of representing string objects.  One is the
-`str` type and the other is the `unicode` type, both of which extend a type
-called `basestring`.  Unfortunately the default is `str` which should not
-be used to store text based information unless only ASCII characters are
-used.  With Python 2.6 it is possible to make `unicode` the default on a per
-module level and with Python 3 it will be the default.
-
-To explicitly use a Unicode string you have to prefix the string literal
-with a `u`: ``u'Hänsel und Gretel sagen Hallo'``.  That way Python will
-store the string as Unicode by decoding the string with the character
-encoding from the current Python module.  If no encoding is specified this
-defaults to 'ASCII' which means that you can't use any non ASCII identifier.
-
-To set a better module encoding add the following comment to the first or
-second line of the Python module using the Unicode literal::
-
-    # -*- coding: utf-8 -*-
-
-We recommend utf-8 as Encoding for Python modules and templates as it's
-possible to represent every Unicode character in utf-8 and because it's
-backwards compatible to ASCII.  For Jinja2 the default encoding of templates
-is assumed to be utf-8.
-
-It is not possible to use Jinja2 to process non-Unicode data.  The reason
-for this is that Jinja2 uses Unicode already on the language level.  For
-example Jinja2 treats the non-breaking space as valid whitespace inside
-expressions which requires knowledge of the encoding or operating on an
-Unicode string.
-
-For more details about Unicode in Python have a look at the excellent
-`Unicode documentation`_.
-
-Another important thing is how Jinja2 is handling string literals in
-templates.  A naive implementation would be using Unicode strings for
-all string literals but it turned out in the past that this is problematic
-as some libraries are typechecking against `str` explicitly.  For example
-`datetime.strftime` does not accept Unicode arguments.  To not break it
-completely Jinja2 is returning `str` for strings that fit into ASCII and
-for everything else `unicode`:
-
->>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
->>> m.a
-'foo'
->>> m.b
-u'f\xf6\xf6'
-
-
-.. _Unicode documentation: http://docs.python.org/dev/howto/unicode.html
-
-High Level API
---------------
-
-The high-level API is the API you will use in the application to load and
-render Jinja2 templates.  The :ref:`low-level-api` on the other side is only
-useful if you want to dig deeper into Jinja2 or :ref:`develop extensions
-<jinja-extensions>`.
-
-.. autoclass:: Environment([options])
-    :members: from_string, get_template, select_template,
-              get_or_select_template, join_path, extend, compile_expression
-
-    .. attribute:: shared
-
-        If a template was created by using the :class:`Template` constructor
-        an environment is created automatically.  These environments are
-        created as shared environments which means that multiple templates
-        may have the same anonymous environment.  For all shared environments
-        this attribute is `True`, else `False`.
-
-    .. attribute:: sandboxed
-
-        If the environment is sandboxed this attribute is `True`.  For the
-        sandbox mode have a look at the documentation for the
-        :class:`~ambari_jinja2.sandbox.SandboxedEnvironment`.
-
-    .. attribute:: filters
-
-        A dict of filters for this environment.  As long as no template was
-        loaded it's safe to add new filters or remove old.  For custom filters
-        see :ref:`writing-filters`.  For valid filter names have a look at
-        :ref:`identifier-naming`.
-
-    .. attribute:: tests
-
-        A dict of test functions for this environment.  As long as no
-        template was loaded it's safe to modify this dict.  For custom tests
-        see :ref:`writing-tests`.  For valid test names have a look at
-        :ref:`identifier-naming`.
-
-    .. attribute:: globals
-
-        A dict of global variables.  These variables are always available
-        in a template.  As long as no template was loaded it's safe
-        to modify this dict.  For more details see :ref:`global-namespace`.
-        For valid object names have a look at :ref:`identifier-naming`.
-
-    .. automethod:: overlay([options])
-
-    .. method:: undefined([hint, obj, name, exc])
-
-        Creates a new :class:`Undefined` object for `name`.  This is useful
-        for filters or functions that may return undefined objects for
-        some operations.  All parameters except of `hint` should be provided
-        as keyword parameters for better readability.  The `hint` is used as
-        error message for the exception if provided, otherwise the error
-        message will be generated from `obj` and `name` automatically.  The exception
-        provided as `exc` is raised if something with the generated undefined
-        object is done that the undefined object does not allow.  The default
-        exception is :exc:`UndefinedError`.  If a `hint` is provided the
-        `name` may be ommited.
-
-        The most common way to create an undefined object is by providing
-        a name only::
-
-            return environment.undefined(name='some_name')
-
-        This means that the name `some_name` is not defined.  If the name
-        was from an attribute of an object it makes sense to tell the
-        undefined object the holder object to improve the error message::
-
-            if not hasattr(obj, 'attr'):
-                return environment.undefined(obj=obj, name='attr')
-
-        For a more complex example you can provide a hint.  For example
-        the :func:`first` filter creates an undefined object that way::
-
-            return environment.undefined('no first item, sequence was empty')            
-
-        If it the `name` or `obj` is known (for example because an attribute
-        was accessed) it shold be passed to the undefined object, even if
-        a custom `hint` is provided.  This gives undefined objects the
-        possibility to enhance the error message.
-
-.. autoclass:: Template
-    :members: module, make_module
-
-    .. attribute:: globals
-
-        The dict with the globals of that template.  It's unsafe to modify
-        this dict as it may be shared with other templates or the environment
-        that loaded the template.
-
-    .. attribute:: name
-
-        The loading name of the template.  If the template was loaded from a
-        string this is `None`.
-
-    .. attribute:: filename
-
-        The filename of the template on the file system if it was loaded from
-        there.  Otherwise this is `None`.
-
-    .. automethod:: render([context])
-
-    .. automethod:: generate([context])
-
-    .. automethod:: stream([context])
-
-
-.. autoclass:: ambari_jinja2.environment.TemplateStream()
-    :members: disable_buffering, enable_buffering, dump
-
-
-Autoescaping
-------------
-
-.. versionadded:: 2.4
-
-As of Jinja 2.4 the preferred way to do autoescaping is to enable the
-:ref:`autoescape-extension` and to configure a sensible default for
-autoescaping.  This makes it possible to enable and disable autoescaping
-on a per-template basis (HTML versus text for instance).
-
-Here a recommended setup that enables autoescaping for templates ending
-in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
-for all other extensions::
-
-    def guess_autoescape(template_name):
-        if template_name is None or '.' not in template_name:
-            return False
-        ext = template_name.rsplit('.', 1)[1]
-        return ext in ('html', 'htm', 'xml')
-
-    env = Environment(autoescape=guess_autoescape,
-                      loader=PackageLoader('mypackage'),
-                      extensions=['ambari_jinja2.ext.autoescape'])
-
-When implementing a guessing autoescape function, make sure you also
-accept `None` as valid template name.  This will be passed when generating
-templates from strings.
-
-Inside the templates the behaviour can be temporarily changed by using
-the `autoescape` block (see :ref:`autoescape-overrides`).
-
-
-.. _identifier-naming:
-
-Notes on Identifiers
---------------------
-
-Jinja2 uses the regular Python 2.x naming rules.  Valid identifiers have to
-match ``[a-zA-Z_][a-zA-Z0-9_]*``.  As a matter of fact non ASCII characters
-are currently not allowed.  This limitation will probably go away as soon as
-unicode identifiers are fully specified for Python 3.
-
-Filters and tests are looked up in separate namespaces and have slightly
-modified identifier syntax.  Filters and tests may contain dots to group
-filters and tests by topic.  For example it's perfectly valid to add a
-function into the filter dict and call it `to.unicode`.  The regular
-expression for filter and test identifiers is
-``[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*```.
-
-
-Undefined Types
----------------
-
-These classes can be used as undefined types.  The :class:`Environment`
-constructor takes an `undefined` parameter that can be one of those classes
-or a custom subclass of :class:`Undefined`.  Whenever the template engine is
-unable to look up a name or access an attribute one of those objects is
-created and returned.  Some operations on undefined values are then allowed,
-others fail.
-
-The closest to regular Python behavior is the `StrictUndefined` which
-disallows all operations beside testing if it's an undefined object.
-
-.. autoclass:: ambari_jinja2.Undefined()
-
-    .. attribute:: _undefined_hint
-
-        Either `None` or an unicode string with the error message for
-        the undefined object.
-
-    .. attribute:: _undefined_obj
-
-        Either `None` or the owner object that caused the undefined object
-        to be created (for example because an attribute does not exist).
-
-    .. attribute:: _undefined_name
-
-        The name for the undefined variable / attribute or just `None`
-        if no such information exists.
-
-    .. attribute:: _undefined_exception
-
-        The exception that the undefined object wants to raise.  This
-        is usually one of :exc:`UndefinedError` or :exc:`SecurityError`.
-
-    .. method:: _fail_with_undefined_error(\*args, \**kwargs)
-
-        When called with any arguments this method raises
-        :attr:`_undefined_exception` with an error message generated
-        from the undefined hints stored on the undefined object.
-
-.. autoclass:: ambari_jinja2.DebugUndefined()
-
-.. autoclass:: ambari_jinja2.StrictUndefined()
-
-Undefined objects are created by calling :attr:`undefined`.
-
-.. admonition:: Implementation
-
-    :class:`Undefined` objects are implemented by overriding the special
-    `__underscore__` methods.  For example the default :class:`Undefined`
-    class implements `__unicode__` in a way that it returns an empty
-    string, however `__int__` and others still fail with an exception.  To
-    allow conversion to int by returning ``0`` you can implement your own::
-
-        class NullUndefined(Undefined):
-            def __int__(self):
-                return 0
-            def __float__(self):
-                return 0.0
-
-    To disallow a method, just override it and raise
-    :attr:`~Undefined._undefined_exception`.  Because this is a very common
-    idom in undefined objects there is the helper method
-    :meth:`~Undefined._fail_with_undefined_error` that does the error raising
-    automatically.  Here a class that works like the regular :class:`Undefined`
-    but chokes on iteration::
-
-        class NonIterableUndefined(Undefined):
-            __iter__ = Undefined._fail_with_undefined_error
-
-
-The Context
------------
-
-.. autoclass:: ambari_jinja2.runtime.Context()
-    :members: resolve, get_exported, get_all
-
-    .. attribute:: parent
-
-        A dict of read only, global variables the template looks up.  These
-        can either come from another :class:`Context`, from the
-        :attr:`Environment.globals` or :attr:`Template.globals` or points
-        to a dict created by combining the globals with the variables
-        passed to the render function.  It must not be altered.
-
-    .. attribute:: vars
-
-        The template local variables.  This list contains environment and
-        context functions from the :attr:`parent` scope as well as local
-        modifications and exported variables from the template.  The template
-        will modify this dict during template evaluation but filters and
-        context functions are not allowed to modify it.
-
-    .. attribute:: environment
-
-        The environment that loaded the template.
-
-    .. attribute:: exported_vars
-
-        This set contains all the names the template exports.  The values for
-        the names are in the :attr:`vars` dict.  In order to get a copy of the
-        exported variables as dict, :meth:`get_exported` can be used.
-
-    .. attribute:: name
-
-        The load name of the template owning this context.
-
-    .. attribute:: blocks
-
-        A dict with the current mapping of blocks in the template.  The keys
-        in this dict are the names of the blocks, and the values a list of
-        blocks registered.  The last item in each list is the current active
-        block (latest in the inheritance chain).
-
-    .. attribute:: eval_ctx
-
-        The current :ref:`eval-context`.
-
-    .. automethod:: ambari_jinja2.runtime.Context.call(callable, \*args, \**kwargs)
-
-
-.. admonition:: Implementation
-
-    Context is immutable for the same reason Python's frame locals are
-    immutable inside functions.  Both Jinja2 and Python are not using the
-    context / frame locals as data storage for variables but only as primary
-    data source.
-
-    When a template accesses a variable the template does not define, Jinja2
-    looks up the variable in the context, after that the variable is treated
-    as if it was defined in the template.
-
-
-.. _loaders:
-
-Loaders
--------
-
-Loaders are responsible for loading templates from a resource such as the
-file system.  The environment will keep the compiled modules in memory like
-Python's `sys.modules`.  Unlike `sys.modules` however this cache is limited in
-size by default and templates are automatically reloaded.
-All loaders are subclasses of :class:`BaseLoader`.  If you want to create your
-own loader, subclass :class:`BaseLoader` and override `get_source`.
-
-.. autoclass:: ambari_jinja2.BaseLoader
-    :members: get_source, load
-
-Here a list of the builtin loaders Jinja2 provides:
-
-.. autoclass:: ambari_jinja2.FileSystemLoader
-
-.. autoclass:: ambari_jinja2.PackageLoader
-
-.. autoclass:: ambari_jinja2.DictLoader
-
-.. autoclass:: ambari_jinja2.FunctionLoader
-
-.. autoclass:: ambari_jinja2.PrefixLoader
-
-.. autoclass:: ambari_jinja2.ChoiceLoader
-
-
-.. _bytecode-cache:
-
-Bytecode Cache
---------------
-
-Jinja 2.1 and higher support external bytecode caching.  Bytecode caches make
-it possible to store the generated bytecode on the file system or a different
-location to avoid parsing the templates on first use.
-
-This is especially useful if you have a web application that is initialized on
-the first request and Jinja compiles many templates at once which slows down
-the application.
-
-To use a bytecode cache, instanciate it and pass it to the :class:`Environment`.
-
-.. autoclass:: ambari_jinja2.BytecodeCache
-    :members: load_bytecode, dump_bytecode, clear
-
-.. autoclass:: ambari_jinja2.bccache.Bucket
-    :members: write_bytecode, load_bytecode, bytecode_from_string,
-              bytecode_to_string, reset
-
-    .. attribute:: environment
-
-        The :class:`Environment` that created the bucket.
-
-    .. attribute:: key
-
-        The unique cache key for this bucket
-
-    .. attribute:: code
-
-        The bytecode if it's loaded, otherwise `None`.
-
-
-Builtin bytecode caches:
-
-.. autoclass:: ambari_jinja2.FileSystemBytecodeCache
-
-.. autoclass:: ambari_jinja2.MemcachedBytecodeCache
-
-
-Utilities
----------
-
-These helper functions and classes are useful if you add custom filters or
-functions to a Jinja2 environment.
-
-.. autofunction:: ambari_jinja2.environmentfilter
-
-.. autofunction:: ambari_jinja2.contextfilter
-
-.. autofunction:: ambari_jinja2.evalcontextfilter
-
-.. autofunction:: ambari_jinja2.environmentfunction
-
-.. autofunction:: ambari_jinja2.contextfunction
-
-.. autofunction:: ambari_jinja2.evalcontextfunction
-
-.. function:: escape(s)
-
-    Convert the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in string `s`
-    to HTML-safe sequences.  Use this if you need to display text that might
-    contain such characters in HTML.  This function will not escaped objects
-    that do have an HTML representation such as already escaped data.
-
-    The return value is a :class:`Markup` string.
-
-.. autofunction:: ambari_jinja2.clear_caches
-
-.. autofunction:: ambari_jinja2.is_undefined
-
-.. autoclass:: ambari_jinja2.Markup([string])
-    :members: escape, unescape, striptags
-
-.. admonition:: Note
-
-    The Jinja2 :class:`Markup` class is compatible with at least Pylons and
-    Genshi.  It's expected that more template engines and framework will pick
-    up the `__html__` concept soon.
-
-
-Exceptions
-----------
-
-.. autoexception:: ambari_jinja2.TemplateError
-
-.. autoexception:: ambari_jinja2.UndefinedError
-
-.. autoexception:: ambari_jinja2.TemplateNotFound
-
-.. autoexception:: ambari_jinja2.TemplatesNotFound
-
-.. autoexception:: ambari_jinja2.TemplateSyntaxError
-
-    .. attribute:: message
-
-        The error message as utf-8 bytestring.
-
-    .. attribute:: lineno
-
-        The line number where the error occurred
-
-    .. attribute:: name
-
-        The load name for the template as unicode string.
-
-    .. attribute:: filename
-
-        The filename that loaded the template as bytestring in the encoding
-        of the file system (most likely utf-8 or mbcs on Windows systems).
-
-    The reason why the filename and error message are bytestrings and not
-    unicode strings is that Python 2.x is not using unicode for exceptions
-    and tracebacks as well as the compiler.  This will change with Python 3.
-
-.. autoexception:: ambari_jinja2.TemplateAssertionError
-
-
-.. _writing-filters:
-
-Custom Filters
---------------
-
-Custom filters are just regular Python functions that take the left side of
-the filter as first argument and the the arguments passed to the filter as
-extra arguments or keyword arguments.
-
-For example in the filter ``{{ 42|myfilter(23) }}`` the function would be
-called with ``myfilter(42, 23)``.  Here for example a simple filter that can
-be applied to datetime objects to format them::
-
-    def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
-        return value.strftime(format)
-
-You can register it on the template environment by updating the
-:attr:`~Environment.filters` dict on the environment::
-
-    environment.filters['datetimeformat'] = datetimeformat
-
-Inside the template it can then be used as follows:
-
-.. sourcecode:: jinja
-
-    written on: {{ article.pub_date|datetimeformat }}
-    publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}
-
-Filters can also be passed the current template context or environment.  This
-is useful if a filter wants to return an undefined value or check the current
-:attr:`~Environment.autoescape` setting.  For this purpose three decorators
-exist: :func:`environmentfilter`, :func:`contextfilter` and
-:func:`evalcontextfilter`.
-
-Here a small example filter that breaks a text into HTML line breaks and
-paragraphs and marks the return value as safe HTML string if autoescaping is
-enabled::
-
-    import re
-    from ambari_jinja2 import environmentfilter, Markup, escape
-
-    _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
-
-    @evalcontextfilter
-    def nl2br(eval_ctx, value):
-        result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
-                              for p in _paragraph_re.split(escape(value)))
-        if eval_ctx.autoescape:
-            result = Markup(result)
-        return result
-
-Context filters work the same just that the first argument is the current
-active :class:`Context` rather then the environment.
-
-
-.. _eval-context:
-
-Evaluation Context
-------------------
-
-The evaluation context (short eval context or eval ctx) is a new object
-introducted in Jinja 2.4 that makes it possible to activate and deactivate
-compiled features at runtime.
-
-Currently it is only used to enable and disable the automatic escaping but
-can be used for extensions as well.
-
-In previous Jinja versions filters and functions were marked as
-environment callables in order to check for the autoescape status from the
-environment.  In new versions it's encouraged to check the setting from the
-evaluation context instead.
-
-Previous versions::
-
-    @environmentfilter
-    def filter(env, value):
-        result = do_something(value)
-        if env.autoescape:
-            result = Markup(result)
-        return result
-
-In new versions you can either use a :func:`contextfilter` and access the
-evaluation context from the actual context, or use a
-:func:`evalcontextfilter` which directly passes the evaluation context to
-the function::
-
-    @contextfilter
-    def filter(context, value):
-        result = do_something(value)
-        if context.eval_ctx.autoescape:
-            result = Markup(result)
-        return result
-
-    @evalcontextfilter
-    def filter(eval_ctx, value):
-        result = do_something(value)
-        if eval_ctx.autoescape:
-            result = Markup(result)
-        return result
-
-The evaluation context must not be modified at runtime.  Modifications
-must only happen with a :class:`nodes.EvalContextModifier` and
-:class:`nodes.ScopedEvalContextModifier` from an extension, not on the
-eval context object itself.
-
-.. autoclass:: ambari_jinja2.nodes.EvalContext
-
-   .. attribute:: autoescape
-
-      `True` or `False` depending on if autoescaping is active or not.
-
-   .. attribute:: volatile
-
-      `True` if the compiler cannot evaluate some expressions at compile
-      time.  At runtime this should always be `False`.
-
-
-.. _writing-tests:
-
-Custom Tests
-------------
-
-Tests work like filters just that there is no way for a test to get access
-to the environment or context and that they can't be chained.  The return
-value of a test should be `True` or `False`.  The purpose of a test is to
-give the template designers the possibility to perform type and conformability
-checks.
-
-Here a simple test that checks if a variable is a prime number::
-
-    import math
-
-    def is_prime(n):
-        if n == 2:
-            return True
-        for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
-            if n % i == 0:
-                return False
-        return True
-        
-
-You can register it on the template environment by updating the
-:attr:`~Environment.tests` dict on the environment::
-
-    environment.tests['prime'] = is_prime
-
-A template designer can then use the test like this:
-
-.. sourcecode:: jinja
-
-    {% if 42 is prime %}
-        42 is a prime number
-    {% else %}
-        42 is not a prime number
-    {% endif %}
-
-
-.. _global-namespace:
-
-The Global Namespace
---------------------
-
-Variables stored in the :attr:`Environment.globals` dict are special as they
-are available for imported templates too, even if they are imported without
-context.  This is the place where you can put variables and functions
-that should be available all the time.  Additionally :attr:`Template.globals`
-exist that are variables available to a specific template that are available
-to all :meth:`~Template.render` calls.
-
-
-.. _low-level-api:
-
-Low Level API
--------------
-
-The low level API exposes functionality that can be useful to understand some
-implementation details, debugging purposes or advanced :ref:`extension
-<jinja-extensions>` techniques.  Unless you know exactly what you are doing we
-don't recommend using any of those.
-
-.. automethod:: Environment.lex
-
-.. automethod:: Environment.parse
-
-.. automethod:: Environment.preprocess
-
-.. automethod:: Template.new_context
-
-.. method:: Template.root_render_func(context)
-
-    This is the low level render function.  It's passed a :class:`Context`
-    that has to be created by :meth:`new_context` of the same template or
-    a compatible template.  This render function is generated by the
-    compiler from the template code and returns a generator that yields
-    unicode strings.
-
-    If an exception in the template code happens the template engine will
-    not rewrite the exception but pass through the original one.  As a
-    matter of fact this function should only be called from within a
-    :meth:`render` / :meth:`generate` / :meth:`stream` call.
-
-.. attribute:: Template.blocks
-
-    A dict of block render functions.  Each of these functions works exactly
-    like the :meth:`root_render_func` with the same limitations.
-
-.. attribute:: Template.is_up_to_date
-
-    This attribute is `False` if there is a newer version of the template
-    available, otherwise `True`.
-
-.. admonition:: Note
-
-    The low-level API is fragile.  Future Jinja2 versions will try not to
-    change it in a backwards incompatible way but modifications in the Jinja2
-    core may shine through.  For example if Jinja2 introduces a new AST node
-    in later versions that may be returned by :meth:`~Environment.parse`.
-
-The Meta API
-------------
-
-.. versionadded:: 2.2
-
-The meta API returns some information about abstract syntax trees that
-could help applications to implement more advanced template concepts.  All
-the functions of the meta API operate on an abstract syntax tree as
-returned by the :meth:`Environment.parse` method.
-
-.. autofunction:: ambari_jinja2.meta.find_undeclared_variables
-
-.. autofunction:: ambari_jinja2.meta.find_referenced_templates

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py b/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py
deleted file mode 100644
index d3703e3..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from ambari_jinja2 import nodes
-from ambari_jinja2.ext import Extension
-
-
-class FragmentCacheExtension(Extension):
-    # a set of names that trigger the extension.
-    tags = set(['cache'])
-
-    def __init__(self, environment):
-        super(FragmentCacheExtension, self).__init__(environment)
-
-        # add the defaults to the environment
-        environment.extend(
-            fragment_cache_prefix='',
-            fragment_cache=None
-        )
-
-    def parse(self, parser):
-        # the first token is the token that started the tag.  In our case
-        # we only listen to ``'cache'`` so this will be a name token with
-        # `cache` as value.  We get the line number so that we can give
-        # that line number to the nodes we create by hand.
-        lineno = parser.stream.next().lineno
-
-        # now we parse a single expression that is used as cache key.
-        args = [parser.parse_expression()]
-
-        # if there is a comma, the user provided a timeout.  If not use
-        # None as second parameter.
-        if parser.stream.skip_if('comma'):
-            args.append(parser.parse_expression())
-        else:
-            args.append(nodes.Const(None))
-
-        # now we parse the body of the cache block up to `endcache` and
-        # drop the needle (which would always be `endcache` in that case)
-        body = parser.parse_statements(['name:endcache'], drop_needle=True)
-
-        # now return a `CallBlock` node that calls our _cache_support
-        # helper method on this extension.
-        return nodes.CallBlock(self.call_method('_cache_support', args),
-                               [], [], body).set_lineno(lineno)
-
-    def _cache_support(self, name, timeout, caller):
-        """Helper callback."""
-        key = self.environment.fragment_cache_prefix + name
-
-        # try to load the block from the cache
-        # if there is no fragment in the cache, render it and store
-        # it in the cache.
-        rv = self.environment.fragment_cache.get(key)
-        if rv is not None:
-            return rv
-        rv = caller()
-        self.environment.fragment_cache.add(key, rv, timeout)
-        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst b/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst
deleted file mode 100644
index 6d6d6ca..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-.. module:: ambari_jinja2
-
-.. include:: ../CHANGES

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/conf.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/conf.py b/ambari-common/src/main/python/ambari_jinja2/docs/conf.py
deleted file mode 100644
index ba90c49..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/conf.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Jinja2 documentation build configuration file, created by
-# sphinx-quickstart on Sun Apr 27 21:42:41 2008.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
-#
-# All configuration values have a default value; values that are commented out
-# serve to show the default value.
-
-import sys, os
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-sys.path.append(os.path.dirname(os.path.abspath(__file__)))
-
-# General configuration
-# ---------------------
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'jinjaext']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General substitutions.
-project = 'Jinja2'
-copyright = '2008, Armin Ronacher'
-
-# The default replacements for |version| and |release|, also used in various
-# other places throughout the built documents.
-#
-# The short X.Y version.
-version = '2.0'
-# The full version, including alpha/beta/rc tags.
-release = '2.0'
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%B %d, %Y'
-
-# List of documents that shouldn't be included in the build.
-#unused_docs = []
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'jinjaext.JinjaStyle'
-
-
-# Options for HTML output
-# -----------------------
-
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-html_style = 'style.css'
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# no modindex
-html_use_modindex = False
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.
-#html_use_opensearch = False
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'Jinja2doc'
-
-
-# Options for LaTeX output
-# ------------------------
-
-# The paper size ('letter' or 'a4').
-latex_paper_size = 'a4'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, document class [howto/manual]).
-latex_documents = [
-  ('index', 'Jinja2.tex', 'Jinja2 Documentation', 'Armin Ronacher', 'manual', 'toctree_only'),
-]
-
-# Additional stuff for the LaTeX preamble.
-latex_preamble = '''
-\usepackage{palatino}
-\definecolor{TitleColor}{rgb}{0.7,0,0}
-\definecolor{InnerLinkColor}{rgb}{0.7,0,0}
-\definecolor{OuterLinkColor}{rgb}{0.8,0,0}
-\definecolor{VerbatimColor}{rgb}{0.985,0.985,0.985}
-\definecolor{VerbatimBorderColor}{rgb}{0.8,0.8,0.8}
-'''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-latex_use_modindex = False

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst b/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst
deleted file mode 100644
index 4d2c458..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst
+++ /dev/null
@@ -1,347 +0,0 @@
-.. _jinja-extensions:
-
-Extensions
-==========
-
-Jinja2 supports extensions that can add extra filters, tests, globals or even
-extend the parser.  The main motivation of extensions is it to move often used
-code into a reusable class like adding support for internationalization.
-
-
-Adding Extensions
------------------
-
-Extensions are added to the Jinja2 environment at creation time.  Once the
-environment is created additional extensions cannot be added.  To add an
-extension pass a list of extension classes or import paths to the
-`environment` parameter of the :class:`Environment` constructor.  The following
-example creates a Jinja2 environment with the i18n extension loaded::
-
-    jinja_env = Environment(extensions=['ambari_jinja2.ext.i18n'])
-
-
-.. _i18n-extension:
-
-i18n Extension
---------------
-
-**Import name:** `ambari_jinja2.ext.i18n`
-
-Jinja2 currently comes with one extension, the i18n extension.  It can be
-used in combination with `gettext`_ or `babel`_.  If the i18n extension is
-enabled Jinja2 provides a `trans` statement that marks the wrapped string as
-translatable and calls `gettext`.
-
-After enabling dummy `_` function that forwards calls to `gettext` is added
-to the environment globals.  An internationalized application then has to
-provide at least an `gettext` and optoinally a `ngettext` function into the
-namespace.  Either globally or for each rendering.
-
-Environment Methods
-~~~~~~~~~~~~~~~~~~~
-
-After enabling of the extension the environment provides the following
-additional methods:
-
-.. method:: ambari_jinja2.Environment.install_gettext_translations(translations, newstyle=False)
-
-    Installs a translation globally for that environment.  The tranlations
-    object provided must implement at least `ugettext` and `ungettext`.
-    The `gettext.NullTranslations` and `gettext.GNUTranslations` classes
-    as well as `Babel`_\s `Translations` class are supported.
-
-    .. versionchanged:: 2.5 newstyle gettext added
-
-.. method:: ambari_jinja2.Environment.install_null_translations(newstyle=False)
-
-    Install dummy gettext functions.  This is useful if you want to prepare
-    the application for internationalization but don't want to implement the
-    full internationalization system yet.
-
-    .. versionchanged:: 2.5 newstyle gettext added
-
-.. method:: ambari_jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False)
-
-    Installs the given `gettext` and `ngettext` callables into the
-    environment as globals.  They are supposed to behave exactly like the
-    standard library's :func:`gettext.ugettext` and
-    :func:`gettext.ungettext` functions.
-
-    If `newstyle` is activated, the callables are wrapped to work like
-    newstyle callables.  See :ref:`newstyle-gettext` for more information.
-
-    .. versionadded:: 2.5
-
-.. method:: ambari_jinja2.Environment.uninstall_gettext_translations()
-
-    Uninstall the translations again.
-
-.. method:: ambari_jinja2.Environment.extract_translations(source)
-
-    Extract localizable strings from the given template node or source.
-
-    For every string found this function yields a ``(lineno, function,
-    message)`` tuple, where:
-
-    * `lineno` is the number of the line on which the string was found,
-    * `function` is the name of the `gettext` function used (if the
-      string was extracted from embedded Python code), and
-    *  `message` is the string itself (a `unicode` object, or a tuple
-       of `unicode` objects for functions with multiple string arguments).
-
-    If `Babel`_ is installed :ref:`the babel integration <babel-integration>`
-    can be used to extract strings for babel.
-
-For a web application that is available in multiple languages but gives all
-the users the same language (for example a multilingual forum software
-installed for a French community) may load the translations once and add the
-translation methods to the environment at environment generation time::
-
-    translations = get_gettext_translations()
-    env = Environment(extensions=['ambari_jinja2.ext.i18n'])
-    env.install_gettext_translations(translations)
-
-The `get_gettext_translations` function would return the translator for the
-current configuration.  (For example by using `gettext.find`)
-
-The usage of the `i18n` extension for template designers is covered as part
-:ref:`of the template documentation <i18n-in-templates>`.
-
-.. _gettext: http://docs.python.org/dev/library/gettext
-.. _Babel: http://babel.edgewall.org/
-
-.. _newstyle-gettext:
-
-Newstyle Gettext
-~~~~~~~~~~~~~~~~
-
-.. versionadded:: 2.5
-
-Starting with version 2.5 you can use newstyle gettext calls.  These are
-inspired by trac's internal gettext functions and are fully supported by
-the babel extraction tool.  They might not work as expected by other
-extraction tools in case you are not using Babel's.
-
-What's the big difference between standard and newstyle gettext calls?  In
-general they are less to type and less error prone.  Also if they are used
-in an autoescaping environment they better support automatic escaping.
-Here some common differences between old and new calls:
-
-standard gettext:
-
-.. sourcecode:: html+jinja
-
-    {{ gettext('Hello World!') }}
-    {{ gettext('Hello %(name)s!')|format(name='World') }}
-    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count)|format(
-        num=apples|count
-    )}}
-
-newstyle gettext looks like this instead:
-
-.. sourcecode:: html+jinja
-
-    {{ gettext('Hello World!') }}
-    {{ gettext('Hello %(name)s!', name='World') }}
-    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
-
-The advantages of newstyle gettext is that you have less to type and that
-named placeholders become mandatory.  The latter sounds like a
-disadvantage but solves a lot of troubles translators are often facing
-when they are unable to switch the positions of two placeholder.  With
-newstyle gettext, all format strings look the same.
-
-Furthermore with newstyle gettext, string formatting is also used if no
-placeholders are used which makes all strings behave exactly the same.
-Last but not least are newstyle gettext calls able to properly mark
-strings for autoescaping which solves lots of escaping related issues many
-templates are experiencing over time when using autoescaping.
-
-Expression Statement
---------------------
-
-**Import name:** `ambari_jinja2.ext.do`
-
-The "do" aka expression-statement extension adds a simple `do` tag to the
-template engine that works like a variable expression but ignores the
-return value.
-
-.. _loopcontrols-extension:
-
-Loop Controls
--------------
-
-**Import name:** `ambari_jinja2.ext.loopcontrols`
-
-This extension adds support for `break` and `continue` in loops.  After
-enabling Jinja2 provides those two keywords which work exactly like in
-Python.
-
-.. _with-extension:
-
-With Statement
---------------
-
-**Import name:** `ambari_jinja2.ext.with_`
-
-.. versionadded:: 2.3
-
-This extension adds support for the with keyword.  Using this keyword it
-is possible to enforce a nested scope in a template.  Variables can be
-declared directly in the opening block of the with statement or using a
-standard `set` statement directly within.
-
-.. _autoescape-extension:
-
-Autoescape Extension
---------------------
-
-**Import name:** `ambari_jinja2.ext.autoescape`
-
-.. versionadded:: 2.4
-
-The autoescape extension allows you to toggle the autoescape feature from
-within the template.  If the environment's :attr:`~Environment.autoescape`
-setting is set to `False` it can be activated, if it's `True` it can be
-deactivated.  The setting overriding is scoped.
-
-
-.. _writing-extensions:
-
-Writing Extensions
-------------------
-
-.. module:: ambari_jinja2.ext
-
-By writing extensions you can add custom tags to Jinja2.  This is a non trival
-task and usually not needed as the default tags and expressions cover all
-common use cases.  The i18n extension is a good example of why extensions are
-useful, another one would be fragment caching.
-
-When writing extensions you have to keep in mind that you are working with the
-Jinja2 template compiler which does not validate the node tree you are possing
-to it.  If the AST is malformed you will get all kinds of compiler or runtime
-errors that are horrible to debug.  Always make sure you are using the nodes
-you create correctly.  The API documentation below shows which nodes exist and
-how to use them.
-
-Example Extension
-~~~~~~~~~~~~~~~~~
-
-The following example implements a `cache` tag for Jinja2 by using the
-`Werkzeug`_ caching contrib module:
-
-.. literalinclude:: cache_extension.py
-    :language: python
-
-And here is how you use it in an environment::
-
-    from ambari_jinja2 import Environment
-    from werkzeug.contrib.cache import SimpleCache
-
-    env = Environment(extensions=[FragmentCacheExtension])
-    env.fragment_cache = SimpleCache()
-
-Inside the template it's then possible to mark blocks as cacheable.  The
-following example caches a sidebar for 300 seconds:
-
-.. sourcecode:: html+jinja
-
-    {% cache 'sidebar', 300 %}
-    <div class="sidebar">
-        ...
-    </div>
-    {% endcache %}
-
-.. _Werkzeug: http://werkzeug.pocoo.org/
-
-Extension API
-~~~~~~~~~~~~~
-
-Extensions always have to extend the :class:`ambari_jinja2.ext.Extension` class:
-
-.. autoclass:: Extension
-    :members: preprocess, filter_stream, parse, attr, call_method
-
-    .. attribute:: identifier
-
-        The identifier of the extension.  This is always the true import name
-        of the extension class and must not be changed.
-
-    .. attribute:: tags
-
-        If the extension implements custom tags this is a set of tag names
-        the extension is listening for.
-
-Parser API
-~~~~~~~~~~
-
-The parser passed to :meth:`Extension.parse` provides ways to parse
-expressions of different types.  The following methods may be used by
-extensions:
-
-.. autoclass:: ambari_jinja2.parser.Parser
-    :members: parse_expression, parse_tuple, parse_assign_target,
-              parse_statements, free_identifier, fail
-
-    .. attribute:: filename
-
-        The filename of the template the parser processes.  This is **not**
-        the load name of the template.  For the load name see :attr:`name`.
-        For templates that were not loaded form the file system this is
-        `None`.
-
-    .. attribute:: name
-
-        The load name of the template.
-
-    .. attribute:: stream
-
-        The current :class:`~ambari_jinja2.lexer.TokenStream`
-
-.. autoclass:: ambari_jinja2.lexer.TokenStream
-   :members: push, look, eos, skip, next, next_if, skip_if, expect
-
-   .. attribute:: current
-
-        The current :class:`~ambari_jinja2.lexer.Token`.
-
-.. autoclass:: ambari_jinja2.lexer.Token
-    :members: test, test_any
-
-    .. attribute:: lineno
-
-        The line number of the token
-
-    .. attribute:: type
-
-        The type of the token.  This string is interned so you may compare
-        it with arbitrary strings using the `is` operator.
-
-    .. attribute:: value
-
-        The value of the token.
-
-There is also a utility function in the lexer module that can count newline
-characters in strings:
-
-.. autofunction:: ambari_jinja2.lexer.count_newlines
-
-AST
-~~~
-
-The AST (Abstract Syntax Tree) is used to represent a template after parsing.
-It's build of nodes that the compiler then converts into executable Python
-code objects.  Extensions that provide custom statements can return nodes to
-execute custom Python code.
-
-The list below describes all nodes that are currently available.  The AST may
-change between Jinja2 versions but will stay backwards compatible.
-
-For more information have a look at the repr of :meth:`ambari_jinja2.Environment.parse`.
-
-.. module:: ambari_jinja2.nodes
-
-.. jinjanodes::
-
-.. autoexception:: Impossible

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst b/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst
deleted file mode 100644
index 89186b1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst
+++ /dev/null
@@ -1,191 +0,0 @@
-Frequently Asked Questions
-==========================
-
-This page answers some of the often asked questions about Jinja.
-
-.. highlight:: html+jinja
-
-Why is it called Jinja?
------------------------
-
-The name Jinja was chosen because it's the name of a Japanese temple and
-temple and template share a similar pronunciation.  It is not named after
-the capital city of Uganda.
-
-How fast is it?
----------------
-
-We really hate benchmarks especially since they don't reflect much.  The
-performance of a template depends on many factors and you would have to
-benchmark different engines in different situations.  The benchmarks from the
-testsuite show that Jinja2 has a similar performance to `Mako`_ and is between
-10 and 20 times faster than Django's template engine or Genshi.  These numbers
-should be taken with tons of salt as the benchmarks that took these numbers
-only test a few performance related situations such as looping.  Generally
-speaking the performance of a template engine doesn't matter much as the
-usual bottleneck in a web application is either the database or the application
-code.
-
-.. _Mako: http://www.makotemplates.org/
-
-How Compatible is Jinja2 with Django?
--------------------------------------
-
-The default syntax of Jinja2 matches Django syntax in many ways.  However
-this similarity doesn't mean that you can use a Django template unmodified
-in Jinja2.  For example filter arguments use a function call syntax rather
-than a colon to separate filter name and arguments.  Additionally the
-extension interface in Jinja is fundamentally different from the Django one
-which means that your custom tags won't work any longer.
-
-Generally speaking you will use much less custom extensions as the Jinja
-template system allows you to use a certain subset of Python expressions
-which can replace most Django extensions.  For example instead of using
-something like this::
-
-    {% load comments %}
-    {% get_latest_comments 10 as latest_comments %}
-    {% for comment in latest_comments %}
-        ...
-    {% endfor %}
-
-You will most likely provide an object with attributes to retrieve
-comments from the database::
-
-    {% for comment in models.comments.latest(10) %}
-        ...
-    {% endfor %}
-
-Or directly provide the model for quick testing::
-
-    {% for comment in Comment.objects.order_by('-pub_date')[:10] %}
-        ...
-    {% endfor %}
-
-Please keep in mind that even though you may put such things into templates
-it still isn't a good idea.  Queries should go into the view code and not
-the template!
-
-Isn't it a terrible idea to put Logic into Templates?
------------------------------------------------------
-
-Without a doubt you should try to remove as much logic from templates as
-possible.  But templates without any logic mean that you have to do all
-the processing in the code which is boring and stupid.  A template engine
-that does that is shipped with Python and called `string.Template`.  Comes
-without loops and if conditions and is by far the fastest template engine
-you can get for Python.
-
-So some amount of logic is required in templates to keep everyone happy.
-And Jinja leaves it pretty much to you how much logic you want to put into
-templates.  There are some restrictions in what you can do and what not.
-
-Jinja2 neither allows you to put arbitrary Python code into templates nor
-does it allow all Python expressions.  The operators are limited to the
-most common ones and more advanced expressions such as list comprehensions
-and generator expressions are not supported.  This keeps the template engine
-easier to maintain and templates more readable.
-
-Why is Autoescaping not the Default?
-------------------------------------
-
-There are multiple reasons why automatic escaping is not the default mode
-and also not the recommended one.  While automatic escaping of variables
-means that you will less likely have an XSS problem it also causes a huge
-amount of extra processing in the template engine which can cause serious
-performance problems.  As Python doesn't provide a way to mark strings as
-unsafe Jinja has to hack around that limitation by providing a custom
-string class (the :class:`Markup` string) that safely interacts with safe
-and unsafe strings.
-
-With explicit escaping however the template engine doesn't have to perform
-any safety checks on variables.  Also a human knows not to escape integers
-or strings that may never contain characters one has to escape or already
-HTML markup.  For example when iterating over a list over a table of
-integers and floats for a table of statistics the template designer can
-omit the escaping because he knows that integers or floats don't contain
-any unsafe parameters.
-
-Additionally Jinja2 is a general purpose template engine and not only used
-for HTML/XML generation.  For example you may generate LaTeX, emails,
-CSS, JavaScript, or configuration files.
-
-Why is the Context immutable?
------------------------------
-
-When writing a :func:`contextfunction` or something similar you may have
-noticed that the context tries to stop you from modifying it.  If you have
-managed to modify the context by using an internal context API you may
-have noticed that changes in the context don't seem to be visible in the
-template.  The reason for this is that Jinja uses the context only as
-primary data source for template variables for performance reasons.
-
-If you want to modify the context write a function that returns a variable
-instead that one can assign to a variable by using set::
-
-    {% set comments = get_latest_comments() %}
-
-What is the speedups module and why is it missing?
---------------------------------------------------
-
-To achieve a good performance with automatic escaping enabled, the escaping
-function was also implemented in pure C in older Jinja2 releases and used if
-Jinja2 was installed with the speedups module.
-
-Because this feature itself is very useful for non-template engines as
-well it was moved into a separate project on PyPI called `MarkupSafe`_.
-
-Jinja2 no longer ships with a C implementation of it but only the pure
-Python implementation.  It will however check if MarkupSafe is available
-and installed, and if it is, use the Markup class from MarkupSafe.
-
-So if you want the speedups, just import MarkupSafe.
-
-.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
-
-My tracebacks look weird.  What's happening?
---------------------------------------------
-
-If the debugsupport module is not compiled and you are using a Python
-installation without ctypes (Python 2.4 without ctypes, Jython or Google's
-AppEngine) Jinja2 is unable to provide correct debugging information and
-the traceback may be incomplete.  There is currently no good workaround
-for Jython or the AppEngine as ctypes is unavailable there and it's not
-possible to use the debugsupport extension.
-
-Why is there no Python 2.3 support?
------------------------------------
-
-Python 2.3 is missing a lot of features that are used heavily in Jinja2.  This
-decision was made as with the upcoming Python 2.6 and 3.0 versions it becomes
-harder to maintain the code for older Python versions.  If you really need
-Python 2.3 support you either have to use `Jinja 1`_ or other templating
-engines that still support 2.3.
-
-My Macros are overriden by something
-------------------------------------
-
-In some situations the Jinja scoping appears arbitrary:
-
-layout.tmpl:
-
-.. sourcecode:: jinja
-
-    {% macro foo() %}LAYOUT{% endmacro %}
-    {% block body %}{% endblock %}
-
-child.tmpl:
-
-.. sourcecode:: jinja
-
-    {% extends 'layout.tmpl' %}
-    {% macro foo() %}CHILD{% endmacro %}
-    {% block body %}{{ foo() }}{% endblock %}
-
-This will print ``LAYOUT`` in Jinja2.  This is a side effect of having
-the parent template evaluated after the child one.  This allows child
-templates passing information to the parent template.  To avoid this
-issue rename the macro or variable in the parent template to have an
-uncommon prefix.
-
-.. _Jinja 1: http://jinja.pocoo.org/1/

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/index.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/index.rst b/ambari-common/src/main/python/ambari_jinja2/docs/index.rst
deleted file mode 100644
index 27bee23..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/index.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-Jinja2 Documentation
-====================
-
-This is the documentation for the Jinja2 general purpose templating language.
-Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
-fast and secure.
-
-.. toctree::
-   :maxdepth: 2
-
-   intro
-   api
-   sandbox
-   templates
-   extensions
-   integration
-   switching
-   tricks
-
-   faq
-   changelog
-
-If you can't find the information you're looking for, have a look at the
-index of try to find it using the search function:
-
-* :ref:`genindex`
-* :ref:`search`

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst b/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst
deleted file mode 100644
index 4f8614a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst
+++ /dev/null
@@ -1,88 +0,0 @@
-Integration
-===========
-
-Jinja2 provides some code for integration into other tools such as frameworks,
-the `Babel`_ library or your favourite editor for fancy code highlighting.
-This is a brief description of whats included.
-
-.. _babel-integration:
-
-Babel Integration
------------------
-
-Jinja provides support for extracting gettext messages from templates via a
-`Babel`_ extractor entry point called `ambari_jinja2.ext.babel_extract`.  The Babel
-support is implemented as part of the :ref:`i18n-extension` extension.
-
-Gettext messages extracted from both `trans` tags and code expressions.
-
-To extract gettext messages from templates, the project needs a Jinja2 section
-in its Babel extraction method `mapping file`_:
-
-.. sourcecode:: ini
-
-    [ambari_jinja2: **/templates/**.html]
-    encoding = utf-8
-
-The syntax related options of the :class:`Environment` are also available as
-configuration values in the mapping file.  For example to tell the extraction
-that templates use ``%`` as `line_statement_prefix` you can use this code:
-
-.. sourcecode:: ini
-
-    [ambari_jinja2: **/templates/**.html]
-    encoding = utf-8
-    line_statement_prefix = %
-
-:ref:`jinja-extensions` may also be defined by passing a comma separated list
-of import paths as `extensions` value.  The i18n extension is added
-automatically.
-
-.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
-
-Pylons
-------
-
-With `Pylons`_ 0.9.7 onwards it's incredible easy to integrate Jinja into a
-Pylons powered application.
-
-The template engine is configured in `config/environment.py`.  The configuration
-for Jinja2 looks something like that::
-
-    from ambari_jinja2 import Environment, PackageLoader
-    config['pylons.app_globals'].jinja_env = Environment(
-        loader=PackageLoader('yourapplication', 'templates')
-    )
-
-After that you can render Jinja templates by using the `render_jinja` function
-from the `pylons.templating` module.
-
-Additionally it's a good idea to set the Pylons' `c` object into strict mode.
-Per default any attribute to not existing attributes on the `c` object return
-an empty string and not an undefined object.  To change this just use this
-snippet and add it into your `config/environment.py`::
-
-    config['pylons.strict_c'] = True
-
-.. _Pylons: http://www.pylonshq.com/
-
-TextMate
---------
-
-Inside the `ext` folder of Jinja2 there is a bundle for TextMate that supports
-syntax highlighting for Jinja1 and Jinja2 for text based templates as well as
-HTML.  It also contains a few often used snippets.
-
-Vim
----
-
-A syntax plugin for `Vim`_ exists in the Vim-scripts directory as well as the
-ext folder of Jinja2.  `The script <http://www.vim.org/scripts/script.php?script_id=1856>`_
-supports Jinja1 and Jinja2.  Once installed two file types are available `jinja`
-and `htmljinja`.  The first one for text based templates, the latter for HTML
-templates.
-
-Copy the files into your `syntax` folder.
-
-.. _Babel: http://babel.edgewall.org/
-.. _Vim: http://www.vim.org/


[04/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/filters.py b/ambari-common/src/main/python/jinja2/jinja2/filters.py
new file mode 100644
index 0000000..d1848e4
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/filters.py
@@ -0,0 +1,719 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.filters
+    ~~~~~~~~~~~~~~
+
+    Bundled jinja filters.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import math
+from random import choice
+from operator import itemgetter
+from itertools import imap, groupby
+from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
+from jinja2.runtime import Undefined
+from jinja2.exceptions import FilterArgumentError, SecurityError
+
+
+_word_re = re.compile(r'\w+(?u)')
+
+
+def contextfilter(f):
+    """Decorator for marking context dependent filters. The current
+    :class:`Context` will be passed as first argument.
+    """
+    f.contextfilter = True
+    return f
+
+
+def evalcontextfilter(f):
+    """Decorator for marking eval-context dependent filters.  An eval
+    context object is passed as first argument.  For more information
+    about the eval context, see :ref:`eval-context`.
+
+    .. versionadded:: 2.4
+    """
+    f.evalcontextfilter = True
+    return f
+
+
+def environmentfilter(f):
+    """Decorator for marking evironment dependent filters.  The current
+    :class:`Environment` is passed to the filter as first argument.
+    """
+    f.environmentfilter = True
+    return f
+
+
+def do_forceescape(value):
+    """Enforce HTML escaping.  This will probably double escape variables."""
+    if hasattr(value, '__html__'):
+        value = value.__html__()
+    return escape(unicode(value))
+
+
+@evalcontextfilter
+def do_replace(eval_ctx, s, old, new, count=None):
+    """Return a copy of the value with all occurrences of a substring
+    replaced with a new one. The first argument is the substring
+    that should be replaced, the second is the replacement string.
+    If the optional third argument ``count`` is given, only the first
+    ``count`` occurrences are replaced:
+
+    .. sourcecode:: jinja
+
+        {{ "Hello World"|replace("Hello", "Goodbye") }}
+            -> Goodbye World
+
+        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
+            -> d'oh, d'oh, aaargh
+    """
+    if count is None:
+        count = -1
+    if not eval_ctx.autoescape:
+        return unicode(s).replace(unicode(old), unicode(new), count)
+    if hasattr(old, '__html__') or hasattr(new, '__html__') and \
+       not hasattr(s, '__html__'):
+        s = escape(s)
+    else:
+        s = soft_unicode(s)
+    return s.replace(soft_unicode(old), soft_unicode(new), count)
+
+
+def do_upper(s):
+    """Convert a value to uppercase."""
+    return soft_unicode(s).upper()
+
+
+def do_lower(s):
+    """Convert a value to lowercase."""
+    return soft_unicode(s).lower()
+
+
+@evalcontextfilter
+def do_xmlattr(_eval_ctx, d, autospace=True):
+    """Create an SGML/XML attribute string based on the items in a dict.
+    All values that are neither `none` nor `undefined` are automatically
+    escaped:
+
+    .. sourcecode:: html+jinja
+
+        <ul{{ {'class': 'my_list', 'missing': none,
+                'id': 'list-%d'|format(variable)}|xmlattr }}>
+        ...
+        </ul>
+
+    Results in something like this:
+
+    .. sourcecode:: html
+
+        <ul class="my_list" id="list-42">
+        ...
+        </ul>
+
+    As you can see it automatically prepends a space in front of the item
+    if the filter returned something unless the second parameter is false.
+    """
+    rv = u' '.join(
+        u'%s="%s"' % (escape(key), escape(value))
+        for key, value in d.iteritems()
+        if value is not None and not isinstance(value, Undefined)
+    )
+    if autospace and rv:
+        rv = u' ' + rv
+    if _eval_ctx.autoescape:
+        rv = Markup(rv)
+    return rv
+
+
+def do_capitalize(s):
+    """Capitalize a value. The first character will be uppercase, all others
+    lowercase.
+    """
+    return soft_unicode(s).capitalize()
+
+
+def do_title(s):
+    """Return a titlecased version of the value. I.e. words will start with
+    uppercase letters, all remaining characters are lowercase.
+    """
+    return soft_unicode(s).title()
+
+
+def do_dictsort(value, case_sensitive=False, by='key'):
+    """Sort a dict and yield (key, value) pairs. Because python dicts are
+    unsorted you may want to use this function to order them by either
+    key or value:
+
+    .. sourcecode:: jinja
+
+        {% for item in mydict|dictsort %}
+            sort the dict by key, case insensitive
+
+        {% for item in mydict|dicsort(true) %}
+            sort the dict by key, case sensitive
+
+        {% for item in mydict|dictsort(false, 'value') %}
+            sort the dict by key, case insensitive, sorted
+            normally and ordered by value.
+    """
+    if by == 'key':
+        pos = 0
+    elif by == 'value':
+        pos = 1
+    else:
+        raise FilterArgumentError('You can only sort by either '
+                                  '"key" or "value"')
+    def sort_func(item):
+        value = item[pos]
+        if isinstance(value, basestring) and not case_sensitive:
+            value = value.lower()
+        return value
+
+    return sorted(value.items(), key=sort_func)
+
+
+def do_sort(value, reverse=False, case_sensitive=False):
+    """Sort an iterable.  Per default it sorts ascending, if you pass it
+    true as first argument it will reverse the sorting.
+
+    If the iterable is made of strings the third parameter can be used to
+    control the case sensitiveness of the comparison which is disabled by
+    default.
+
+    .. sourcecode:: jinja
+
+        {% for item in iterable|sort %}
+            ...
+        {% endfor %}
+    """
+    if not case_sensitive:
+        def sort_func(item):
+            if isinstance(item, basestring):
+                item = item.lower()
+            return item
+    else:
+        sort_func = None
+    return sorted(value, key=sort_func, reverse=reverse)
+
+
+def do_default(value, default_value=u'', boolean=False):
+    """If the value is undefined it will return the passed default value,
+    otherwise the value of the variable:
+
+    .. sourcecode:: jinja
+
+        {{ my_variable|default('my_variable is not defined') }}
+
+    This will output the value of ``my_variable`` if the variable was
+    defined, otherwise ``'my_variable is not defined'``. If you want
+    to use default with variables that evaluate to false you have to
+    set the second parameter to `true`:
+
+    .. sourcecode:: jinja
+
+        {{ ''|default('the string was empty', true) }}
+    """
+    if (boolean and not value) or isinstance(value, Undefined):
+        return default_value
+    return value
+
+
+@evalcontextfilter
+def do_join(eval_ctx, value, d=u''):
+    """Return a string which is the concatenation of the strings in the
+    sequence. The separator between elements is an empty string per
+    default, you can define it with the optional parameter:
+
+    .. sourcecode:: jinja
+
+        {{ [1, 2, 3]|join('|') }}
+            -> 1|2|3
+
+        {{ [1, 2, 3]|join }}
+            -> 123
+    """
+    # no automatic escaping?  joining is a lot eaiser then
+    if not eval_ctx.autoescape:
+        return unicode(d).join(imap(unicode, value))
+
+    # if the delimiter doesn't have an html representation we check
+    # if any of the items has.  If yes we do a coercion to Markup
+    if not hasattr(d, '__html__'):
+        value = list(value)
+        do_escape = False
+        for idx, item in enumerate(value):
+            if hasattr(item, '__html__'):
+                do_escape = True
+            else:
+                value[idx] = unicode(item)
+        if do_escape:
+            d = escape(d)
+        else:
+            d = unicode(d)
+        return d.join(value)
+
+    # no html involved, to normal joining
+    return soft_unicode(d).join(imap(soft_unicode, value))
+
+
+def do_center(value, width=80):
+    """Centers the value in a field of a given width."""
+    return unicode(value).center(width)
+
+
+@environmentfilter
+def do_first(environment, seq):
+    """Return the first item of a sequence."""
+    try:
+        return iter(seq).next()
+    except StopIteration:
+        return environment.undefined('No first item, sequence was empty.')
+
+
+@environmentfilter
+def do_last(environment, seq):
+    """Return the last item of a sequence."""
+    try:
+        return iter(reversed(seq)).next()
+    except StopIteration:
+        return environment.undefined('No last item, sequence was empty.')
+
+
+@environmentfilter
+def do_random(environment, seq):
+    """Return a random item from the sequence."""
+    try:
+        return choice(seq)
+    except IndexError:
+        return environment.undefined('No random item, sequence was empty.')
+
+
+def do_filesizeformat(value, binary=False):
+    """Format the value like a 'human-readable' file size (i.e. 13 KB,
+    4.1 MB, 102 bytes, etc).  Per default decimal prefixes are used (mega,
+    giga, etc.), if the second parameter is set to `True` the binary
+    prefixes are used (mebi, gibi).
+    """
+    bytes = float(value)
+    base = binary and 1024 or 1000
+    middle = binary and 'i' or ''
+    if bytes < base:
+        return "%d Byte%s" % (bytes, bytes != 1 and 's' or '')
+    elif bytes < base * base:
+        return "%.1f K%sB" % (bytes / base, middle)
+    elif bytes < base * base * base:
+        return "%.1f M%sB" % (bytes / (base * base), middle)
+    return "%.1f G%sB" % (bytes / (base * base * base), middle)
+
+
+def do_pprint(value, verbose=False):
+    """Pretty print a variable. Useful for debugging.
+
+    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
+    is truthy the output will be more verbose (this requires `pretty`)
+    """
+    return pformat(value, verbose=verbose)
+
+
+@evalcontextfilter
+def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
+    """Converts URLs in plain text into clickable links.
+
+    If you pass the filter an additional integer it will shorten the urls
+    to that number. Also a third argument exists that makes the urls
+    "nofollow":
+
+    .. sourcecode:: jinja
+
+        {{ mytext|urlize(40, true) }}
+            links are shortened to 40 chars and defined with rel="nofollow"
+    """
+    rv = urlize(value, trim_url_limit, nofollow)
+    if eval_ctx.autoescape:
+        rv = Markup(rv)
+    return rv
+
+
+def do_indent(s, width=4, indentfirst=False):
+    """Return a copy of the passed string, each line indented by
+    4 spaces. The first line is not indented. If you want to
+    change the number of spaces or indent the first line too
+    you can pass additional parameters to the filter:
+
+    .. sourcecode:: jinja
+
+        {{ mytext|indent(2, true) }}
+            indent by two spaces and indent the first line too.
+    """
+    indention = u' ' * width
+    rv = (u'\n' + indention).join(s.splitlines())
+    if indentfirst:
+        rv = indention + rv
+    return rv
+
+
+def do_truncate(s, length=255, killwords=False, end='...'):
+    """Return a truncated copy of the string. The length is specified
+    with the first parameter which defaults to ``255``. If the second
+    parameter is ``true`` the filter will cut the text at length. Otherwise
+    it will try to save the last word. If the text was in fact
+    truncated it will append an ellipsis sign (``"..."``). If you want a
+    different ellipsis sign than ``"..."`` you can specify it using the
+    third parameter.
+
+    .. sourcecode jinja::
+
+        {{ mytext|truncate(300, false, '&raquo;') }}
+            truncate mytext to 300 chars, don't split up words, use a
+            right pointing double arrow as ellipsis sign.
+    """
+    if len(s) <= length:
+        return s
+    elif killwords:
+        return s[:length] + end
+    words = s.split(' ')
+    result = []
+    m = 0
+    for word in words:
+        m += len(word) + 1
+        if m > length:
+            break
+        result.append(word)
+    result.append(end)
+    return u' '.join(result)
+
+
+def do_wordwrap(s, width=79, break_long_words=True):
+    """
+    Return a copy of the string passed to the filter wrapped after
+    ``79`` characters.  You can override this default using the first
+    parameter.  If you set the second parameter to `false` Jinja will not
+    split words apart if they are longer than `width`.
+    """
+    import textwrap
+    return u'\n'.join(textwrap.wrap(s, width=width, expand_tabs=False,
+                                   replace_whitespace=False,
+                                   break_long_words=break_long_words))
+
+
+def do_wordcount(s):
+    """Count the words in that string."""
+    return len(_word_re.findall(s))
+
+
+def do_int(value, default=0):
+    """Convert the value into an integer. If the
+    conversion doesn't work it will return ``0``. You can
+    override this default using the first parameter.
+    """
+    try:
+        return int(value)
+    except (TypeError, ValueError):
+        # this quirk is necessary so that "42.23"|int gives 42.
+        try:
+            return int(float(value))
+        except (TypeError, ValueError):
+            return default
+
+
+def do_float(value, default=0.0):
+    """Convert the value into a floating point number. If the
+    conversion doesn't work it will return ``0.0``. You can
+    override this default using the first parameter.
+    """
+    try:
+        return float(value)
+    except (TypeError, ValueError):
+        return default
+
+
+def do_format(value, *args, **kwargs):
+    """
+    Apply python string formatting on an object:
+
+    .. sourcecode:: jinja
+
+        {{ "%s - %s"|format("Hello?", "Foo!") }}
+            -> Hello? - Foo!
+    """
+    if args and kwargs:
+        raise FilterArgumentError('can\'t handle positional and keyword '
+                                  'arguments at the same time')
+    return soft_unicode(value) % (kwargs or args)
+
+
+def do_trim(value):
+    """Strip leading and trailing whitespace."""
+    return soft_unicode(value).strip()
+
+
+def do_striptags(value):
+    """Strip SGML/XML tags and replace adjacent whitespace by one space.
+    """
+    if hasattr(value, '__html__'):
+        value = value.__html__()
+    return Markup(unicode(value)).striptags()
+
+
+def do_slice(value, slices, fill_with=None):
+    """Slice an iterator and return a list of lists containing
+    those items. Useful if you want to create a div containing
+    three ul tags that represent columns:
+
+    .. sourcecode:: html+jinja
+
+        <div class="columwrapper">
+          {%- for column in items|slice(3) %}
+            <ul class="column-{{ loop.index }}">
+            {%- for item in column %}
+              <li>{{ item }}</li>
+            {%- endfor %}
+            </ul>
+          {%- endfor %}
+        </div>
+
+    If you pass it a second argument it's used to fill missing
+    values on the last iteration.
+    """
+    seq = list(value)
+    length = len(seq)
+    items_per_slice = length // slices
+    slices_with_extra = length % slices
+    offset = 0
+    for slice_number in xrange(slices):
+        start = offset + slice_number * items_per_slice
+        if slice_number < slices_with_extra:
+            offset += 1
+        end = offset + (slice_number + 1) * items_per_slice
+        tmp = seq[start:end]
+        if fill_with is not None and slice_number >= slices_with_extra:
+            tmp.append(fill_with)
+        yield tmp
+
+
+def do_batch(value, linecount, fill_with=None):
+    """
+    A filter that batches items. It works pretty much like `slice`
+    just the other way round. It returns a list of lists with the
+    given number of items. If you provide a second parameter this
+    is used to fill missing items. See this example:
+
+    .. sourcecode:: html+jinja
+
+        <table>
+        {%- for row in items|batch(3, '&nbsp;') %}
+          <tr>
+          {%- for column in row %}
+            <td>{{ column }}</td>
+          {%- endfor %}
+          </tr>
+        {%- endfor %}
+        </table>
+    """
+    result = []
+    tmp = []
+    for item in value:
+        if len(tmp) == linecount:
+            yield tmp
+            tmp = []
+        tmp.append(item)
+    if tmp:
+        if fill_with is not None and len(tmp) < linecount:
+            tmp += [fill_with] * (linecount - len(tmp))
+        yield tmp
+
+
+def do_round(value, precision=0, method='common'):
+    """Round the number to a given precision. The first
+    parameter specifies the precision (default is ``0``), the
+    second the rounding method:
+
+    - ``'common'`` rounds either up or down
+    - ``'ceil'`` always rounds up
+    - ``'floor'`` always rounds down
+
+    If you don't specify a method ``'common'`` is used.
+
+    .. sourcecode:: jinja
+
+        {{ 42.55|round }}
+            -> 43.0
+        {{ 42.55|round(1, 'floor') }}
+            -> 42.5
+
+    Note that even if rounded to 0 precision, a float is returned.  If
+    you need a real integer, pipe it through `int`:
+
+    .. sourcecode:: jinja
+
+        {{ 42.55|round|int }}
+            -> 43
+    """
+    if not method in ('common', 'ceil', 'floor'):
+        raise FilterArgumentError('method must be common, ceil or floor')
+    if method == 'common':
+        return round(value, precision)
+    func = getattr(math, method)
+    return func(value * (10 ** precision)) / (10 ** precision)
+
+
+@environmentfilter
+def do_groupby(environment, value, attribute):
+    """Group a sequence of objects by a common attribute.
+
+    If you for example have a list of dicts or objects that represent persons
+    with `gender`, `first_name` and `last_name` attributes and you want to
+    group all users by genders you can do something like the following
+    snippet:
+
+    .. sourcecode:: html+jinja
+
+        <ul>
+        {% for group in persons|groupby('gender') %}
+            <li>{{ group.grouper }}<ul>
+            {% for person in group.list %}
+                <li>{{ person.first_name }} {{ person.last_name }}</li>
+            {% endfor %}</ul></li>
+        {% endfor %}
+        </ul>
+
+    Additionally it's possible to use tuple unpacking for the grouper and
+    list:
+
+    .. sourcecode:: html+jinja
+
+        <ul>
+        {% for grouper, list in persons|groupby('gender') %}
+            ...
+        {% endfor %}
+        </ul>
+
+    As you can see the item we're grouping by is stored in the `grouper`
+    attribute and the `list` contains all the objects that have this grouper
+    in common.
+    """
+    expr = lambda x: environment.getitem(x, attribute)
+    return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
+
+
+class _GroupTuple(tuple):
+    __slots__ = ()
+    grouper = property(itemgetter(0))
+    list = property(itemgetter(1))
+
+    def __new__(cls, (key, value)):
+        return tuple.__new__(cls, (key, list(value)))
+
+
+def do_list(value):
+    """Convert the value into a list.  If it was a string the returned list
+    will be a list of characters.
+    """
+    return list(value)
+
+
+def do_mark_safe(value):
+    """Mark the value as safe which means that in an environment with automatic
+    escaping enabled this variable will not be escaped.
+    """
+    return Markup(value)
+
+
+def do_mark_unsafe(value):
+    """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
+    return unicode(value)
+
+
+def do_reverse(value):
+    """Reverse the object or return an iterator the iterates over it the other
+    way round.
+    """
+    if isinstance(value, basestring):
+        return value[::-1]
+    try:
+        return reversed(value)
+    except TypeError:
+        try:
+            rv = list(value)
+            rv.reverse()
+            return rv
+        except TypeError:
+            raise FilterArgumentError('argument must be iterable')
+
+
+@environmentfilter
+def do_attr(environment, obj, name):
+    """Get an attribute of an object.  ``foo|attr("bar")`` works like
+    ``foo["bar"]`` just that always an attribute is returned and items are not
+    looked up.
+
+    See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
+    """
+    try:
+        name = str(name)
+    except UnicodeError:
+        pass
+    else:
+        try:
+            value = getattr(obj, name)
+        except AttributeError:
+            pass
+        else:
+            if environment.sandboxed and not \
+               environment.is_safe_attribute(obj, name, value):
+                return environment.unsafe_undefined(obj, name)
+            return value
+    return environment.undefined(obj=obj, name=name)
+
+
+FILTERS = {
+    'attr':                 do_attr,
+    'replace':              do_replace,
+    'upper':                do_upper,
+    'lower':                do_lower,
+    'escape':               escape,
+    'e':                    escape,
+    'forceescape':          do_forceescape,
+    'capitalize':           do_capitalize,
+    'title':                do_title,
+    'default':              do_default,
+    'd':                    do_default,
+    'join':                 do_join,
+    'count':                len,
+    'dictsort':             do_dictsort,
+    'sort':                 do_sort,
+    'length':               len,
+    'reverse':              do_reverse,
+    'center':               do_center,
+    'indent':               do_indent,
+    'title':                do_title,
+    'capitalize':           do_capitalize,
+    'first':                do_first,
+    'last':                 do_last,
+    'random':               do_random,
+    'filesizeformat':       do_filesizeformat,
+    'pprint':               do_pprint,
+    'truncate':             do_truncate,
+    'wordwrap':             do_wordwrap,
+    'wordcount':            do_wordcount,
+    'int':                  do_int,
+    'float':                do_float,
+    'string':               soft_unicode,
+    'list':                 do_list,
+    'urlize':               do_urlize,
+    'format':               do_format,
+    'trim':                 do_trim,
+    'striptags':            do_striptags,
+    'slice':                do_slice,
+    'batch':                do_batch,
+    'sum':                  sum,
+    'abs':                  abs,
+    'round':                do_round,
+    'groupby':              do_groupby,
+    'safe':                 do_mark_safe,
+    'xmlattr':              do_xmlattr
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/lexer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/lexer.py b/ambari-common/src/main/python/jinja2/jinja2/lexer.py
new file mode 100644
index 0000000..0d3f696
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/lexer.py
@@ -0,0 +1,681 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.lexer
+    ~~~~~~~~~~~~
+
+    This module implements a Jinja / Python combination lexer. The
+    `Lexer` class provided by this module is used to do some preprocessing
+    for Jinja.
+
+    On the one hand it filters out invalid operators like the bitshift
+    operators we don't allow in templates. On the other hand it separates
+    template code and python code in expressions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+from operator import itemgetter
+from collections import deque
+from jinja2.exceptions import TemplateSyntaxError
+from jinja2.utils import LRUCache, next
+
+
+# cache for the lexers. Exists in order to be able to have multiple
+# environments with the same lexer
+_lexer_cache = LRUCache(50)
+
+# static regular expressions
+whitespace_re = re.compile(r'\s+', re.U)
+string_re = re.compile(r"('([^'\\]*(?:\\.[^'\\]*)*)'"
+                       r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
+integer_re = re.compile(r'\d+')
+
+# we use the unicode identifier rule if this python version is able
+# to handle unicode identifiers, otherwise the standard ASCII one.
+try:
+    compile('föö', '<unknown>', 'eval')
+except SyntaxError:
+    name_re = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b')
+else:
+    from jinja2 import _stringdefs
+    name_re = re.compile(r'[%s][%s]*' % (_stringdefs.xid_start,
+                                         _stringdefs.xid_continue))
+
+float_re = re.compile(r'(?<!\.)\d+\.\d+')
+newline_re = re.compile(r'(\r\n|\r|\n)')
+
+# internal the tokens and keep references to them
+TOKEN_ADD = intern('add')
+TOKEN_ASSIGN = intern('assign')
+TOKEN_COLON = intern('colon')
+TOKEN_COMMA = intern('comma')
+TOKEN_DIV = intern('div')
+TOKEN_DOT = intern('dot')
+TOKEN_EQ = intern('eq')
+TOKEN_FLOORDIV = intern('floordiv')
+TOKEN_GT = intern('gt')
+TOKEN_GTEQ = intern('gteq')
+TOKEN_LBRACE = intern('lbrace')
+TOKEN_LBRACKET = intern('lbracket')
+TOKEN_LPAREN = intern('lparen')
+TOKEN_LT = intern('lt')
+TOKEN_LTEQ = intern('lteq')
+TOKEN_MOD = intern('mod')
+TOKEN_MUL = intern('mul')
+TOKEN_NE = intern('ne')
+TOKEN_PIPE = intern('pipe')
+TOKEN_POW = intern('pow')
+TOKEN_RBRACE = intern('rbrace')
+TOKEN_RBRACKET = intern('rbracket')
+TOKEN_RPAREN = intern('rparen')
+TOKEN_SEMICOLON = intern('semicolon')
+TOKEN_SUB = intern('sub')
+TOKEN_TILDE = intern('tilde')
+TOKEN_WHITESPACE = intern('whitespace')
+TOKEN_FLOAT = intern('float')
+TOKEN_INTEGER = intern('integer')
+TOKEN_NAME = intern('name')
+TOKEN_STRING = intern('string')
+TOKEN_OPERATOR = intern('operator')
+TOKEN_BLOCK_BEGIN = intern('block_begin')
+TOKEN_BLOCK_END = intern('block_end')
+TOKEN_VARIABLE_BEGIN = intern('variable_begin')
+TOKEN_VARIABLE_END = intern('variable_end')
+TOKEN_RAW_BEGIN = intern('raw_begin')
+TOKEN_RAW_END = intern('raw_end')
+TOKEN_COMMENT_BEGIN = intern('comment_begin')
+TOKEN_COMMENT_END = intern('comment_end')
+TOKEN_COMMENT = intern('comment')
+TOKEN_LINESTATEMENT_BEGIN = intern('linestatement_begin')
+TOKEN_LINESTATEMENT_END = intern('linestatement_end')
+TOKEN_LINECOMMENT_BEGIN = intern('linecomment_begin')
+TOKEN_LINECOMMENT_END = intern('linecomment_end')
+TOKEN_LINECOMMENT = intern('linecomment')
+TOKEN_DATA = intern('data')
+TOKEN_INITIAL = intern('initial')
+TOKEN_EOF = intern('eof')
+
+# bind operators to token types
+operators = {
+    '+':            TOKEN_ADD,
+    '-':            TOKEN_SUB,
+    '/':            TOKEN_DIV,
+    '//':           TOKEN_FLOORDIV,
+    '*':            TOKEN_MUL,
+    '%':            TOKEN_MOD,
+    '**':           TOKEN_POW,
+    '~':            TOKEN_TILDE,
+    '[':            TOKEN_LBRACKET,
+    ']':            TOKEN_RBRACKET,
+    '(':            TOKEN_LPAREN,
+    ')':            TOKEN_RPAREN,
+    '{':            TOKEN_LBRACE,
+    '}':            TOKEN_RBRACE,
+    '==':           TOKEN_EQ,
+    '!=':           TOKEN_NE,
+    '>':            TOKEN_GT,
+    '>=':           TOKEN_GTEQ,
+    '<':            TOKEN_LT,
+    '<=':           TOKEN_LTEQ,
+    '=':            TOKEN_ASSIGN,
+    '.':            TOKEN_DOT,
+    ':':            TOKEN_COLON,
+    '|':            TOKEN_PIPE,
+    ',':            TOKEN_COMMA,
+    ';':            TOKEN_SEMICOLON
+}
+
+reverse_operators = dict([(v, k) for k, v in operators.iteritems()])
+assert len(operators) == len(reverse_operators), 'operators dropped'
+operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
+                         sorted(operators, key=lambda x: -len(x))))
+
+ignored_tokens = frozenset([TOKEN_COMMENT_BEGIN, TOKEN_COMMENT,
+                            TOKEN_COMMENT_END, TOKEN_WHITESPACE,
+                            TOKEN_WHITESPACE, TOKEN_LINECOMMENT_BEGIN,
+                            TOKEN_LINECOMMENT_END, TOKEN_LINECOMMENT])
+ignore_if_empty = frozenset([TOKEN_WHITESPACE, TOKEN_DATA,
+                             TOKEN_COMMENT, TOKEN_LINECOMMENT])
+
+
+def _describe_token_type(token_type):
+    if token_type in reverse_operators:
+        return reverse_operators[token_type]
+    return {
+        TOKEN_COMMENT_BEGIN:        'begin of comment',
+        TOKEN_COMMENT_END:          'end of comment',
+        TOKEN_COMMENT:              'comment',
+        TOKEN_LINECOMMENT:          'comment',
+        TOKEN_BLOCK_BEGIN:          'begin of statement block',
+        TOKEN_BLOCK_END:            'end of statement block',
+        TOKEN_VARIABLE_BEGIN:       'begin of print statement',
+        TOKEN_VARIABLE_END:         'end of print statement',
+        TOKEN_LINESTATEMENT_BEGIN:  'begin of line statement',
+        TOKEN_LINESTATEMENT_END:    'end of line statement',
+        TOKEN_DATA:                 'template data / text',
+        TOKEN_EOF:                  'end of template'
+    }.get(token_type, token_type)
+
+
+def describe_token(token):
+    """Returns a description of the token."""
+    if token.type == 'name':
+        return token.value
+    return _describe_token_type(token.type)
+
+
+def describe_token_expr(expr):
+    """Like `describe_token` but for token expressions."""
+    if ':' in expr:
+        type, value = expr.split(':', 1)
+        if type == 'name':
+            return value
+    else:
+        type = expr
+    return _describe_token_type(type)
+
+
+def count_newlines(value):
+    """Count the number of newline characters in the string.  This is
+    useful for extensions that filter a stream.
+    """
+    return len(newline_re.findall(value))
+
+
+def compile_rules(environment):
+    """Compiles all the rules from the environment into a list of rules."""
+    e = re.escape
+    rules = [
+        (len(environment.comment_start_string), 'comment',
+         e(environment.comment_start_string)),
+        (len(environment.block_start_string), 'block',
+         e(environment.block_start_string)),
+        (len(environment.variable_start_string), 'variable',
+         e(environment.variable_start_string))
+    ]
+
+    if environment.line_statement_prefix is not None:
+        rules.append((len(environment.line_statement_prefix), 'linestatement',
+                      r'^\s*' + e(environment.line_statement_prefix)))
+    if environment.line_comment_prefix is not None:
+        rules.append((len(environment.line_comment_prefix), 'linecomment',
+                      r'(?:^|(?<=\S))[^\S\r\n]*' +
+                      e(environment.line_comment_prefix)))
+
+    return [x[1:] for x in sorted(rules, reverse=True)]
+
+
+class Failure(object):
+    """Class that raises a `TemplateSyntaxError` if called.
+    Used by the `Lexer` to specify known errors.
+    """
+
+    def __init__(self, message, cls=TemplateSyntaxError):
+        self.message = message
+        self.error_class = cls
+
+    def __call__(self, lineno, filename):
+        raise self.error_class(self.message, lineno, filename)
+
+
+class Token(tuple):
+    """Token class."""
+    __slots__ = ()
+    lineno, type, value = (property(itemgetter(x)) for x in range(3))
+
+    def __new__(cls, lineno, type, value):
+        return tuple.__new__(cls, (lineno, intern(str(type)), value))
+
+    def __str__(self):
+        if self.type in reverse_operators:
+            return reverse_operators[self.type]
+        elif self.type == 'name':
+            return self.value
+        return self.type
+
+    def test(self, expr):
+        """Test a token against a token expression.  This can either be a
+        token type or ``'token_type:token_value'``.  This can only test
+        against string values and types.
+        """
+        # here we do a regular string equality check as test_any is usually
+        # passed an iterable of not interned strings.
+        if self.type == expr:
+            return True
+        elif ':' in expr:
+            return expr.split(':', 1) == [self.type, self.value]
+        return False
+
+    def test_any(self, *iterable):
+        """Test against multiple token expressions."""
+        for expr in iterable:
+            if self.test(expr):
+                return True
+        return False
+
+    def __repr__(self):
+        return 'Token(%r, %r, %r)' % (
+            self.lineno,
+            self.type,
+            self.value
+        )
+
+
+class TokenStreamIterator(object):
+    """The iterator for tokenstreams.  Iterate over the stream
+    until the eof token is reached.
+    """
+
+    def __init__(self, stream):
+        self.stream = stream
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        token = self.stream.current
+        if token.type is TOKEN_EOF:
+            self.stream.close()
+            raise StopIteration()
+        next(self.stream)
+        return token
+
+
+class TokenStream(object):
+    """A token stream is an iterable that yields :class:`Token`\s.  The
+    parser however does not iterate over it but calls :meth:`next` to go
+    one token ahead.  The current active token is stored as :attr:`current`.
+    """
+
+    def __init__(self, generator, name, filename):
+        self._next = iter(generator).next
+        self._pushed = deque()
+        self.name = name
+        self.filename = filename
+        self.closed = False
+        self.current = Token(1, TOKEN_INITIAL, '')
+        next(self)
+
+    def __iter__(self):
+        return TokenStreamIterator(self)
+
+    def __nonzero__(self):
+        return bool(self._pushed) or self.current.type is not TOKEN_EOF
+
+    eos = property(lambda x: not x, doc="Are we at the end of the stream?")
+
+    def push(self, token):
+        """Push a token back to the stream."""
+        self._pushed.append(token)
+
+    def look(self):
+        """Look at the next token."""
+        old_token = next(self)
+        result = self.current
+        self.push(result)
+        self.current = old_token
+        return result
+
+    def skip(self, n=1):
+        """Got n tokens ahead."""
+        for x in xrange(n):
+            next(self)
+
+    def next_if(self, expr):
+        """Perform the token test and return the token if it matched.
+        Otherwise the return value is `None`.
+        """
+        if self.current.test(expr):
+            return next(self)
+
+    def skip_if(self, expr):
+        """Like :meth:`next_if` but only returns `True` or `False`."""
+        return self.next_if(expr) is not None
+
+    def next(self):
+        """Go one token ahead and return the old one"""
+        rv = self.current
+        if self._pushed:
+            self.current = self._pushed.popleft()
+        elif self.current.type is not TOKEN_EOF:
+            try:
+                self.current = self._next()
+            except StopIteration:
+                self.close()
+        return rv
+
+    def close(self):
+        """Close the stream."""
+        self.current = Token(self.current.lineno, TOKEN_EOF, '')
+        self._next = None
+        self.closed = True
+
+    def expect(self, expr):
+        """Expect a given token type and return it.  This accepts the same
+        argument as :meth:`jinja2.lexer.Token.test`.
+        """
+        if not self.current.test(expr):
+            expr = describe_token_expr(expr)
+            if self.current.type is TOKEN_EOF:
+                raise TemplateSyntaxError('unexpected end of template, '
+                                          'expected %r.' % expr,
+                                          self.current.lineno,
+                                          self.name, self.filename)
+            raise TemplateSyntaxError("expected token %r, got %r" %
+                                      (expr, describe_token(self.current)),
+                                      self.current.lineno,
+                                      self.name, self.filename)
+        try:
+            return self.current
+        finally:
+            next(self)
+
+
+def get_lexer(environment):
+    """Return a lexer which is probably cached."""
+    key = (environment.block_start_string,
+           environment.block_end_string,
+           environment.variable_start_string,
+           environment.variable_end_string,
+           environment.comment_start_string,
+           environment.comment_end_string,
+           environment.line_statement_prefix,
+           environment.line_comment_prefix,
+           environment.trim_blocks,
+           environment.newline_sequence)
+    lexer = _lexer_cache.get(key)
+    if lexer is None:
+        lexer = Lexer(environment)
+        _lexer_cache[key] = lexer
+    return lexer
+
+
+class Lexer(object):
+    """Class that implements a lexer for a given environment. Automatically
+    created by the environment class, usually you don't have to do that.
+
+    Note that the lexer is not automatically bound to an environment.
+    Multiple environments can share the same lexer.
+    """
+
+    def __init__(self, environment):
+        # shortcuts
+        c = lambda x: re.compile(x, re.M | re.S)
+        e = re.escape
+
+        # lexing rules for tags
+        tag_rules = [
+            (whitespace_re, TOKEN_WHITESPACE, None),
+            (float_re, TOKEN_FLOAT, None),
+            (integer_re, TOKEN_INTEGER, None),
+            (name_re, TOKEN_NAME, None),
+            (string_re, TOKEN_STRING, None),
+            (operator_re, TOKEN_OPERATOR, None)
+        ]
+
+        # assamble the root lexing rule. because "|" is ungreedy
+        # we have to sort by length so that the lexer continues working
+        # as expected when we have parsing rules like <% for block and
+        # <%= for variables. (if someone wants asp like syntax)
+        # variables are just part of the rules if variable processing
+        # is required.
+        root_tag_rules = compile_rules(environment)
+
+        # block suffix if trimming is enabled
+        block_suffix_re = environment.trim_blocks and '\\n?' or ''
+
+        self.newline_sequence = environment.newline_sequence
+
+        # global lexing rules
+        self.rules = {
+            'root': [
+                # directives
+                (c('(.*?)(?:%s)' % '|'.join(
+                    [r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
+                        e(environment.block_start_string),
+                        e(environment.block_start_string),
+                        e(environment.block_end_string),
+                        e(environment.block_end_string)
+                    )] + [
+                        r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, r)
+                        for n, r in root_tag_rules
+                    ])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
+                # data
+                (c('.+'), TOKEN_DATA, None)
+            ],
+            # comments
+            TOKEN_COMMENT_BEGIN: [
+                (c(r'(.*?)((?:\-%s\s*|%s)%s)' % (
+                    e(environment.comment_end_string),
+                    e(environment.comment_end_string),
+                    block_suffix_re
+                )), (TOKEN_COMMENT, TOKEN_COMMENT_END), '#pop'),
+                (c('(.)'), (Failure('Missing end of comment tag'),), None)
+            ],
+            # blocks
+            TOKEN_BLOCK_BEGIN: [
+                (c('(?:\-%s\s*|%s)%s' % (
+                    e(environment.block_end_string),
+                    e(environment.block_end_string),
+                    block_suffix_re
+                )), TOKEN_BLOCK_END, '#pop'),
+            ] + tag_rules,
+            # variables
+            TOKEN_VARIABLE_BEGIN: [
+                (c('\-%s\s*|%s' % (
+                    e(environment.variable_end_string),
+                    e(environment.variable_end_string)
+                )), TOKEN_VARIABLE_END, '#pop')
+            ] + tag_rules,
+            # raw block
+            TOKEN_RAW_BEGIN: [
+                (c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
+                    e(environment.block_start_string),
+                    e(environment.block_start_string),
+                    e(environment.block_end_string),
+                    e(environment.block_end_string),
+                    block_suffix_re
+                )), (TOKEN_DATA, TOKEN_RAW_END), '#pop'),
+                (c('(.)'), (Failure('Missing end of raw directive'),), None)
+            ],
+            # line statements
+            TOKEN_LINESTATEMENT_BEGIN: [
+                (c(r'\s*(\n|$)'), TOKEN_LINESTATEMENT_END, '#pop')
+            ] + tag_rules,
+            # line comments
+            TOKEN_LINECOMMENT_BEGIN: [
+                (c(r'(.*?)()(?=\n|$)'), (TOKEN_LINECOMMENT,
+                 TOKEN_LINECOMMENT_END), '#pop')
+            ]
+        }
+
+    def _normalize_newlines(self, value):
+        """Called for strings and template data to normlize it to unicode."""
+        return newline_re.sub(self.newline_sequence, value)
+
+    def tokenize(self, source, name=None, filename=None, state=None):
+        """Calls tokeniter + tokenize and wraps it in a token stream.
+        """
+        stream = self.tokeniter(source, name, filename, state)
+        return TokenStream(self.wrap(stream, name, filename), name, filename)
+
+    def wrap(self, stream, name=None, filename=None):
+        """This is called with the stream as returned by `tokenize` and wraps
+        every token in a :class:`Token` and converts the value.
+        """
+        for lineno, token, value in stream:
+            if token in ignored_tokens:
+                continue
+            elif token == 'linestatement_begin':
+                token = 'block_begin'
+            elif token == 'linestatement_end':
+                token = 'block_end'
+            # we are not interested in those tokens in the parser
+            elif token in ('raw_begin', 'raw_end'):
+                continue
+            elif token == 'data':
+                value = self._normalize_newlines(value)
+            elif token == 'keyword':
+                token = value
+            elif token == 'name':
+                value = str(value)
+            elif token == 'string':
+                # try to unescape string
+                try:
+                    value = self._normalize_newlines(value[1:-1]) \
+                        .encode('ascii', 'backslashreplace') \
+                        .decode('unicode-escape')
+                except Exception, e:
+                    msg = str(e).split(':')[-1].strip()
+                    raise TemplateSyntaxError(msg, lineno, name, filename)
+                # if we can express it as bytestring (ascii only)
+                # we do that for support of semi broken APIs
+                # as datetime.datetime.strftime.  On python 3 this
+                # call becomes a noop thanks to 2to3
+                try:
+                    value = str(value)
+                except UnicodeError:
+                    pass
+            elif token == 'integer':
+                value = int(value)
+            elif token == 'float':
+                value = float(value)
+            elif token == 'operator':
+                token = operators[value]
+            yield Token(lineno, token, value)
+
+    def tokeniter(self, source, name, filename=None, state=None):
+        """This method tokenizes the text and returns the tokens in a
+        generator.  Use this method if you just want to tokenize a template.
+        """
+        source = '\n'.join(unicode(source).splitlines())
+        pos = 0
+        lineno = 1
+        stack = ['root']
+        if state is not None and state != 'root':
+            assert state in ('variable', 'block'), 'invalid state'
+            stack.append(state + '_begin')
+        else:
+            state = 'root'
+        statetokens = self.rules[stack[-1]]
+        source_length = len(source)
+
+        balancing_stack = []
+
+        while 1:
+            # tokenizer loop
+            for regex, tokens, new_state in statetokens:
+                m = regex.match(source, pos)
+                # if no match we try again with the next rule
+                if m is None:
+                    continue
+
+                # we only match blocks and variables if brances / parentheses
+                # are balanced. continue parsing with the lower rule which
+                # is the operator rule. do this only if the end tags look
+                # like operators
+                if balancing_stack and \
+                   tokens in ('variable_end', 'block_end',
+                              'linestatement_end'):
+                    continue
+
+                # tuples support more options
+                if isinstance(tokens, tuple):
+                    for idx, token in enumerate(tokens):
+                        # failure group
+                        if token.__class__ is Failure:
+                            raise token(lineno, filename)
+                        # bygroup is a bit more complex, in that case we
+                        # yield for the current token the first named
+                        # group that matched
+                        elif token == '#bygroup':
+                            for key, value in m.groupdict().iteritems():
+                                if value is not None:
+                                    yield lineno, key, value
+                                    lineno += value.count('\n')
+                                    break
+                            else:
+                                raise RuntimeError('%r wanted to resolve '
+                                                   'the token dynamically'
+                                                   ' but no group matched'
+                                                   % regex)
+                        # normal group
+                        else:
+                            data = m.group(idx + 1)
+                            if data or token not in ignore_if_empty:
+                                yield lineno, token, data
+                            lineno += data.count('\n')
+
+                # strings as token just are yielded as it.
+                else:
+                    data = m.group()
+                    # update brace/parentheses balance
+                    if tokens == 'operator':
+                        if data == '{':
+                            balancing_stack.append('}')
+                        elif data == '(':
+                            balancing_stack.append(')')
+                        elif data == '[':
+                            balancing_stack.append(']')
+                        elif data in ('}', ')', ']'):
+                            if not balancing_stack:
+                                raise TemplateSyntaxError('unexpected \'%s\'' %
+                                                          data, lineno, name,
+                                                          filename)
+                            expected_op = balancing_stack.pop()
+                            if expected_op != data:
+                                raise TemplateSyntaxError('unexpected \'%s\', '
+                                                          'expected \'%s\'' %
+                                                          (data, expected_op),
+                                                          lineno, name,
+                                                          filename)
+                    # yield items
+                    if data or tokens not in ignore_if_empty:
+                        yield lineno, tokens, data
+                    lineno += data.count('\n')
+
+                # fetch new position into new variable so that we can check
+                # if there is a internal parsing error which would result
+                # in an infinite loop
+                pos2 = m.end()
+
+                # handle state changes
+                if new_state is not None:
+                    # remove the uppermost state
+                    if new_state == '#pop':
+                        stack.pop()
+                    # resolve the new state by group checking
+                    elif new_state == '#bygroup':
+                        for key, value in m.groupdict().iteritems():
+                            if value is not None:
+                                stack.append(key)
+                                break
+                        else:
+                            raise RuntimeError('%r wanted to resolve the '
+                                               'new state dynamically but'
+                                               ' no group matched' %
+                                               regex)
+                    # direct state name given
+                    else:
+                        stack.append(new_state)
+                    statetokens = self.rules[stack[-1]]
+                # we are still at the same position and no stack change.
+                # this means a loop without break condition, avoid that and
+                # raise error
+                elif pos2 == pos:
+                    raise RuntimeError('%r yielded empty string without '
+                                       'stack change' % regex)
+                # publish new function and start again
+                pos = pos2
+                break
+            # if loop terminated without break we havn't found a single match
+            # either we are at the end of the file or we have a problem
+            else:
+                # end of text
+                if pos >= source_length:
+                    return
+                # something went wrong
+                raise TemplateSyntaxError('unexpected char %r at %d' %
+                                          (source[pos], pos), lineno,
+                                          name, filename)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/loaders.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/loaders.py b/ambari-common/src/main/python/jinja2/jinja2/loaders.py
new file mode 100644
index 0000000..bd435e8
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/loaders.py
@@ -0,0 +1,449 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.loaders
+    ~~~~~~~~~~~~~~
+
+    Jinja loader classes.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import weakref
+from types import ModuleType
+from os import path
+try:
+    from hashlib import sha1
+except ImportError:
+    from sha import new as sha1
+from jinja2.exceptions import TemplateNotFound
+from jinja2.utils import LRUCache, open_if_exists, internalcode
+
+
+def split_template_path(template):
+    """Split a path into segments and perform a sanity check.  If it detects
+    '..' in the path it will raise a `TemplateNotFound` error.
+    """
+    pieces = []
+    for piece in template.split('/'):
+        if path.sep in piece \
+           or (path.altsep and path.altsep in piece) or \
+           piece == path.pardir:
+            raise TemplateNotFound(template)
+        elif piece and piece != '.':
+            pieces.append(piece)
+    return pieces
+
+
+class BaseLoader(object):
+    """Baseclass for all loaders.  Subclass this and override `get_source` to
+    implement a custom loading mechanism.  The environment provides a
+    `get_template` method that calls the loader's `load` method to get the
+    :class:`Template` object.
+
+    A very basic example for a loader that looks up templates on the file
+    system could look like this::
+
+        from jinja2 import BaseLoader, TemplateNotFound
+        from os.path import join, exists, getmtime
+
+        class MyLoader(BaseLoader):
+
+            def __init__(self, path):
+                self.path = path
+
+            def get_source(self, environment, template):
+                path = join(self.path, template)
+                if not exists(path):
+                    raise TemplateNotFound(template)
+                mtime = getmtime(path)
+                with file(path) as f:
+                    source = f.read().decode('utf-8')
+                return source, path, lambda: mtime == getmtime(path)
+    """
+
+    #: if set to `False` it indicates that the loader cannot provide access
+    #: to the source of templates.
+    #:
+    #: .. versionadded:: 2.4
+    has_source_access = True
+
+    def get_source(self, environment, template):
+        """Get the template source, filename and reload helper for a template.
+        It's passed the environment and template name and has to return a
+        tuple in the form ``(source, filename, uptodate)`` or raise a
+        `TemplateNotFound` error if it can't locate the template.
+
+        The source part of the returned tuple must be the source of the
+        template as unicode string or a ASCII bytestring.  The filename should
+        be the name of the file on the filesystem if it was loaded from there,
+        otherwise `None`.  The filename is used by python for the tracebacks
+        if no loader extension is used.
+
+        The last item in the tuple is the `uptodate` function.  If auto
+        reloading is enabled it's always called to check if the template
+        changed.  No arguments are passed so the function must store the
+        old state somewhere (for example in a closure).  If it returns `False`
+        the template will be reloaded.
+        """
+        if not self.has_source_access:
+            raise RuntimeError('%s cannot provide access to the source' %
+                               self.__class__.__name__)
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        """Iterates over all templates.  If the loader does not support that
+        it should raise a :exc:`TypeError` which is the default behavior.
+        """
+        raise TypeError('this loader cannot iterate over all templates')
+
+    @internalcode
+    def load(self, environment, name, globals=None):
+        """Loads a template.  This method looks up the template in the cache
+        or loads one by calling :meth:`get_source`.  Subclasses should not
+        override this method as loaders working on collections of other
+        loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)
+        will not call this method but `get_source` directly.
+        """
+        code = None
+        if globals is None:
+            globals = {}
+
+        # first we try to get the source for this template together
+        # with the filename and the uptodate function.
+        source, filename, uptodate = self.get_source(environment, name)
+
+        # try to load the code from the bytecode cache if there is a
+        # bytecode cache configured.
+        bcc = environment.bytecode_cache
+        if bcc is not None:
+            bucket = bcc.get_bucket(environment, name, filename, source)
+            code = bucket.code
+
+        # if we don't have code so far (not cached, no longer up to
+        # date) etc. we compile the template
+        if code is None:
+            code = environment.compile(source, name, filename)
+
+        # if the bytecode cache is available and the bucket doesn't
+        # have a code so far, we give the bucket the new code and put
+        # it back to the bytecode cache.
+        if bcc is not None and bucket.code is None:
+            bucket.code = code
+            bcc.set_bucket(bucket)
+
+        return environment.template_class.from_code(environment, code,
+                                                    globals, uptodate)
+
+
+class FileSystemLoader(BaseLoader):
+    """Loads templates from the file system.  This loader can find templates
+    in folders on the file system and is the preferred way to load them.
+
+    The loader takes the path to the templates as string, or if multiple
+    locations are wanted a list of them which is then looked up in the
+    given order:
+
+    >>> loader = FileSystemLoader('/path/to/templates')
+    >>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
+
+    Per default the template encoding is ``'utf-8'`` which can be changed
+    by setting the `encoding` parameter to something else.
+    """
+
+    def __init__(self, searchpath, encoding='utf-8'):
+        if isinstance(searchpath, basestring):
+            searchpath = [searchpath]
+        self.searchpath = list(searchpath)
+        self.encoding = encoding
+
+    def get_source(self, environment, template):
+        pieces = split_template_path(template)
+        for searchpath in self.searchpath:
+            filename = path.join(searchpath, *pieces)
+            f = open_if_exists(filename)
+            if f is None:
+                continue
+            try:
+                contents = f.read().decode(self.encoding)
+            finally:
+                f.close()
+
+            mtime = path.getmtime(filename)
+            def uptodate():
+                try:
+                    return path.getmtime(filename) == mtime
+                except OSError:
+                    return False
+            return contents, filename, uptodate
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        found = set()
+        for searchpath in self.searchpath:
+            for dirpath, dirnames, filenames in os.walk(searchpath):
+                for filename in filenames:
+                    template = os.path.join(dirpath, filename) \
+                        [len(searchpath):].strip(os.path.sep) \
+                                          .replace(os.path.sep, '/')
+                    if template[:2] == './':
+                        template = template[2:]
+                    if template not in found:
+                        found.add(template)
+        return sorted(found)
+
+
+class PackageLoader(BaseLoader):
+    """Load templates from python eggs or packages.  It is constructed with
+    the name of the python package and the path to the templates in that
+    package::
+
+        loader = PackageLoader('mypackage', 'views')
+
+    If the package path is not given, ``'templates'`` is assumed.
+
+    Per default the template encoding is ``'utf-8'`` which can be changed
+    by setting the `encoding` parameter to something else.  Due to the nature
+    of eggs it's only possible to reload templates if the package was loaded
+    from the file system and not a zip file.
+    """
+
+    def __init__(self, package_name, package_path='templates',
+                 encoding='utf-8'):
+        from pkg_resources import DefaultProvider, ResourceManager, \
+                                  get_provider
+        provider = get_provider(package_name)
+        self.encoding = encoding
+        self.manager = ResourceManager()
+        self.filesystem_bound = isinstance(provider, DefaultProvider)
+        self.provider = provider
+        self.package_path = package_path
+
+    def get_source(self, environment, template):
+        pieces = split_template_path(template)
+        p = '/'.join((self.package_path,) + tuple(pieces))
+        if not self.provider.has_resource(p):
+            raise TemplateNotFound(template)
+
+        filename = uptodate = None
+        if self.filesystem_bound:
+            filename = self.provider.get_resource_filename(self.manager, p)
+            mtime = path.getmtime(filename)
+            def uptodate():
+                try:
+                    return path.getmtime(filename) == mtime
+                except OSError:
+                    return False
+
+        source = self.provider.get_resource_string(self.manager, p)
+        return source.decode(self.encoding), filename, uptodate
+
+    def list_templates(self):
+        path = self.package_path
+        if path[:2] == './':
+            path = path[2:]
+        elif path == '.':
+            path = ''
+        offset = len(path)
+        results = []
+        def _walk(path):
+            for filename in self.provider.resource_listdir(path):
+                fullname = path + '/' + filename
+                if self.provider.resource_isdir(fullname):
+                    for item in _walk(fullname):
+                        results.append(item)
+                else:
+                    results.append(fullname[offset:].lstrip('/'))
+        _walk(path)
+        results.sort()
+        return results
+
+
+class DictLoader(BaseLoader):
+    """Loads a template from a python dict.  It's passed a dict of unicode
+    strings bound to template names.  This loader is useful for unittesting:
+
+    >>> loader = DictLoader({'index.html': 'source here'})
+
+    Because auto reloading is rarely useful this is disabled per default.
+    """
+
+    def __init__(self, mapping):
+        self.mapping = mapping
+
+    def get_source(self, environment, template):
+        if template in self.mapping:
+            source = self.mapping[template]
+            return source, None, lambda: source != self.mapping.get(template)
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        return sorted(self.mapping)
+
+
+class FunctionLoader(BaseLoader):
+    """A loader that is passed a function which does the loading.  The
+    function becomes the name of the template passed and has to return either
+    an unicode string with the template source, a tuple in the form ``(source,
+    filename, uptodatefunc)`` or `None` if the template does not exist.
+
+    >>> def load_template(name):
+    ...     if name == 'index.html':
+    ...         return '...'
+    ...
+    >>> loader = FunctionLoader(load_template)
+
+    The `uptodatefunc` is a function that is called if autoreload is enabled
+    and has to return `True` if the template is still up to date.  For more
+    details have a look at :meth:`BaseLoader.get_source` which has the same
+    return value.
+    """
+
+    def __init__(self, load_func):
+        self.load_func = load_func
+
+    def get_source(self, environment, template):
+        rv = self.load_func(template)
+        if rv is None:
+            raise TemplateNotFound(template)
+        elif isinstance(rv, basestring):
+            return rv, None, None
+        return rv
+
+
+class PrefixLoader(BaseLoader):
+    """A loader that is passed a dict of loaders where each loader is bound
+    to a prefix.  The prefix is delimited from the template by a slash per
+    default, which can be changed by setting the `delimiter` argument to
+    something else::
+
+        loader = PrefixLoader({
+            'app1':     PackageLoader('mypackage.app1'),
+            'app2':     PackageLoader('mypackage.app2')
+        })
+
+    By loading ``'app1/index.html'`` the file from the app1 package is loaded,
+    by loading ``'app2/index.html'`` the file from the second.
+    """
+
+    def __init__(self, mapping, delimiter='/'):
+        self.mapping = mapping
+        self.delimiter = delimiter
+
+    def get_source(self, environment, template):
+        try:
+            prefix, name = template.split(self.delimiter, 1)
+            loader = self.mapping[prefix]
+        except (ValueError, KeyError):
+            raise TemplateNotFound(template)
+        try:
+            return loader.get_source(environment, name)
+        except TemplateNotFound:
+            # re-raise the exception with the correct fileame here.
+            # (the one that includes the prefix)
+            raise TemplateNotFound(template)
+
+    def list_templates(self):
+        result = []
+        for prefix, loader in self.mapping.iteritems():
+            for template in loader.list_templates():
+                result.append(prefix + self.delimiter + template)
+        return result
+
+
+class ChoiceLoader(BaseLoader):
+    """This loader works like the `PrefixLoader` just that no prefix is
+    specified.  If a template could not be found by one loader the next one
+    is tried.
+
+    >>> loader = ChoiceLoader([
+    ...     FileSystemLoader('/path/to/user/templates'),
+    ...     FileSystemLoader('/path/to/system/templates')
+    ... ])
+
+    This is useful if you want to allow users to override builtin templates
+    from a different location.
+    """
+
+    def __init__(self, loaders):
+        self.loaders = loaders
+
+    def get_source(self, environment, template):
+        for loader in self.loaders:
+            try:
+                return loader.get_source(environment, template)
+            except TemplateNotFound:
+                pass
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        found = set()
+        for loader in self.loaders:
+            found.update(loader.list_templates())
+        return sorted(found)
+
+
+class _TemplateModule(ModuleType):
+    """Like a normal module but with support for weak references"""
+
+
+class ModuleLoader(BaseLoader):
+    """This loader loads templates from precompiled templates.
+
+    Example usage:
+
+    >>> loader = ChoiceLoader([
+    ...     ModuleLoader('/path/to/compiled/templates'),
+    ...     FileSystemLoader('/path/to/templates')
+    ... ])
+    """
+
+    has_source_access = False
+
+    def __init__(self, path):
+        package_name = '_jinja2_module_templates_%x' % id(self)
+
+        # create a fake module that looks for the templates in the
+        # path given.
+        mod = _TemplateModule(package_name)
+        if isinstance(path, basestring):
+            path = [path]
+        else:
+            path = list(path)
+        mod.__path__ = path
+
+        sys.modules[package_name] = weakref.proxy(mod,
+            lambda x: sys.modules.pop(package_name, None))
+
+        # the only strong reference, the sys.modules entry is weak
+        # so that the garbage collector can remove it once the
+        # loader that created it goes out of business.
+        self.module = mod
+        self.package_name = package_name
+
+    @staticmethod
+    def get_template_key(name):
+        return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest()
+
+    @staticmethod
+    def get_module_filename(name):
+        return ModuleLoader.get_template_key(name) + '.py'
+
+    @internalcode
+    def load(self, environment, name, globals=None):
+        key = self.get_template_key(name)
+        module = '%s.%s' % (self.package_name, key)
+        mod = getattr(self.module, module, None)
+        if mod is None:
+            try:
+                mod = __import__(module, None, None, ['root'])
+            except ImportError:
+                raise TemplateNotFound(name)
+
+            # remove the entry from sys.modules, we only want the attribute
+            # on the module object we have stored on the loader.
+            sys.modules.pop(module, None)
+
+        return environment.template_class.from_module_dict(
+            environment, mod.__dict__, globals)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/meta.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/meta.py b/ambari-common/src/main/python/jinja2/jinja2/meta.py
new file mode 100644
index 0000000..3a779a5
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/meta.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.meta
+    ~~~~~~~~~~~
+
+    This module implements various functions that exposes information about
+    templates that might be interesting for various kinds of applications.
+
+    :copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details.
+    :license: BSD, see LICENSE for more details.
+"""
+from jinja2 import nodes
+from jinja2.compiler import CodeGenerator
+
+
+class TrackingCodeGenerator(CodeGenerator):
+    """We abuse the code generator for introspection."""
+
+    def __init__(self, environment):
+        CodeGenerator.__init__(self, environment, '<introspection>',
+                               '<introspection>')
+        self.undeclared_identifiers = set()
+
+    def write(self, x):
+        """Don't write."""
+
+    def pull_locals(self, frame):
+        """Remember all undeclared identifiers."""
+        self.undeclared_identifiers.update(frame.identifiers.undeclared)
+
+
+def find_undeclared_variables(ast):
+    """Returns a set of all variables in the AST that will be looked up from
+    the context at runtime.  Because at compile time it's not known which
+    variables will be used depending on the path the execution takes at
+    runtime, all variables are returned.
+
+    >>> from jinja2 import Environment, meta
+    >>> env = Environment()
+    >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+    >>> meta.find_undeclared_variables(ast)
+    set(['bar'])
+
+    .. admonition:: Implementation
+
+       Internally the code generator is used for finding undeclared variables.
+       This is good to know because the code generator might raise a
+       :exc:`TemplateAssertionError` during compilation and as a matter of
+       fact this function can currently raise that exception as well.
+    """
+    codegen = TrackingCodeGenerator(ast.environment)
+    codegen.visit(ast)
+    return codegen.undeclared_identifiers
+
+
+def find_referenced_templates(ast):
+    """Finds all the referenced templates from the AST.  This will return an
+    iterator over all the hardcoded template extensions, inclusions and
+    imports.  If dynamic inheritance or inclusion is used, `None` will be
+    yielded.
+
+    >>> from jinja2 import Environment, meta
+    >>> env = Environment()
+    >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+    >>> list(meta.find_referenced_templates(ast))
+    ['layout.html', None]
+
+    This function is useful for dependency tracking.  For example if you want
+    to rebuild parts of the website after a layout template has changed.
+    """
+    for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import,
+                              nodes.Include)):
+        if not isinstance(node.template, nodes.Const):
+            # a tuple with some non consts in there
+            if isinstance(node.template, (nodes.Tuple, nodes.List)):
+                for template_name in node.template.items:
+                    # something const, only yield the strings and ignore
+                    # non-string consts that really just make no sense
+                    if isinstance(template_name, nodes.Const):
+                        if isinstance(template_name.value, basestring):
+                            yield template_name.value
+                    # something dynamic in there
+                    else:
+                        yield None
+            # something dynamic we don't know about here
+            else:
+                yield None
+            continue
+        # constant is a basestring, direct template name
+        if isinstance(node.template.value, basestring):
+            yield node.template.value
+        # a tuple or list (latter *should* not happen) made of consts,
+        # yield the consts that are strings.  We could warn here for
+        # non string values
+        elif isinstance(node, nodes.Include) and \
+             isinstance(node.template.value, (tuple, list)):
+            for template_name in node.template.value:
+                if isinstance(template_name, basestring):
+                    yield template_name
+        # something else we don't care about, we could warn here
+        else:
+            yield None


[38/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/templates.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/templates.rst b/ambari-common/src/main/python/jinja2/docs/templates.rst
deleted file mode 100644
index 4a1f6ff..0000000
--- a/ambari-common/src/main/python/jinja2/docs/templates.rst
+++ /dev/null
@@ -1,1365 +0,0 @@
-Template Designer Documentation
-===============================
-
-.. highlight:: html+jinja
-
-This document describes the syntax and semantics of the template engine and
-will be most useful as reference to those creating Jinja templates.  As the
-template engine is very flexible the configuration from the application might
-be slightly different from here in terms of delimiters and behavior of
-undefined values.
-
-
-Synopsis
---------
-
-A template is simply a text file.  It can generate any text-based format
-(HTML, XML, CSV, LaTeX, etc.).  It doesn't have a specific extension,
-``.html`` or ``.xml`` are just fine.
-
-A template contains **variables** or **expressions**, which get replaced with
-values when the template is evaluated, and tags, which control the logic of
-the template.  The template syntax is heavily inspired by Django and Python.
-
-Below is a minimal template that illustrates a few basics.  We will cover
-the details later in that document::
-
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-    <html lang="en">
-    <head>
-        <title>My Webpage</title>
-    </head>
-    <body>
-        <ul id="navigation">
-        {% for item in navigation %}
-            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
-        {% endfor %}
-        </ul>
-
-        <h1>My Webpage</h1>
-        {{ a_variable }}
-    </body>
-    </html>
-
-This covers the default settings.  The application developer might have
-changed the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar.
-
-There are two kinds of delimiers. ``{% ... %}`` and ``{{ ... }}``.  The first
-one is used to execute statements such as for-loops or assign values, the
-latter prints the result of the expression to the template.
-
-.. _variables:
-
-Variables
----------
-
-The application passes variables to the templates you can mess around in the
-template.  Variables may have attributes or elements on them you can access
-too.  How a variable looks like, heavily depends on the application providing
-those.
-
-You can use a dot (``.``) to access attributes of a variable, alternative the
-so-called "subscript" syntax (``[]``) can be used.  The following lines do
-the same::
-
-    {{ foo.bar }}
-    {{ foo['bar'] }}
-
-It's important to know that the curly braces are *not* part of the variable
-but the print statement.  If you access variables inside tags don't put the
-braces around.
-
-If a variable or attribute does not exist you will get back an undefined
-value.  What you can do with that kind of value depends on the application
-configuration, the default behavior is that it evaluates to an empty string
-if printed and that you can iterate over it, but every other operation fails.
-
-.. _notes-on-subscriptions:
-
-.. admonition:: Implementation
-
-    For convenience sake ``foo.bar`` in Jinja2 does the following things on
-    the Python layer:
-
-    -   check if there is an attribute called `bar` on `foo`.
-    -   if there is not, check if there is an item ``'bar'`` in `foo`.
-    -   if there is not, return an undefined object.
-
-    ``foo['bar']`` on the other hand works mostly the same with the a small
-    difference in the order:
-
-    -   check if there is an item ``'bar'`` in `foo`.
-    -   if there is not, check if there is an attribute called `bar` on `foo`.
-    -   if there is not, return an undefined object.
-
-    This is important if an object has an item or attribute with the same
-    name.  Additionally there is the :func:`attr` filter that just looks up
-    attributes.
-
-.. _filters:
-
-Filters
--------
-
-Variables can by modified by **filters**.  Filters are separated from the
-variable by a pipe symbol (``|``) and may have optional arguments in
-parentheses.  Multiple filters can be chained.  The output of one filter is
-applied to the next.
-
-``{{ name|striptags|title }}`` for example will remove all HTML Tags from the
-`name` and title-cases it.  Filters that accept arguments have parentheses
-around the arguments, like a function call.  This example will join a list
-by commas:  ``{{ list|join(', ') }}``.
-
-The :ref:`builtin-filters` below describes all the builtin filters.
-
-.. _tests:
-
-Tests
------
-
-Beside filters there are also so called "tests" available.  Tests can be used
-to test a variable against a common expression.  To test a variable or
-expression you add `is` plus the name of the test after the variable.  For
-example to find out if a variable is defined you can do ``name is defined``
-which will then return true or false depending on if `name` is defined.
-
-Tests can accept arguments too.  If the test only takes one argument you can
-leave out the parentheses to group them.  For example the following two
-expressions do the same::
-
-    {% if loop.index is divisibleby 3 %}
-    {% if loop.index is divisibleby(3) %}
-
-The :ref:`builtin-tests` below describes all the builtin tests.
-
-
-Comments
---------
-
-To comment-out part of a line in a template, use the comment syntax which is
-by default set to ``{# ... #}``.  This is useful to comment out parts of the
-template for debugging or to add information for other template designers or
-yourself::
-
-    {# note: disabled template because we no longer use this
-        {% for user in users %}
-            ...
-        {% endfor %}
-    #}
-
-
-Whitespace Control
-------------------
-
-In the default configuration whitespace is not further modified by the
-template engine, so each whitespace (spaces, tabs, newlines etc.) is returned
-unchanged.  If the application configures Jinja to `trim_blocks` the first
-newline after a a template tag is removed automatically (like in PHP).
-
-But you can also strip whitespace in templates by hand.  If you put an minus
-sign (``-``) to the start or end of an block (for example a for tag), a
-comment or variable expression you can remove the whitespaces after or before
-that block::
-
-    {% for item in seq -%}
-        {{ item }}
-    {%- endfor %}
-    
-This will yield all elements without whitespace between them.  If `seq` was
-a list of numbers from ``1`` to ``9`` the output would be ``123456789``.
-
-If :ref:`line-statements` are enabled they strip leading whitespace
-automatically up to the beginning of the line.
-
-.. admonition:: Note
-
-    You must not use a whitespace between the tag and the minus sign.
-
-    **valid**::
-
-        {%- if foo -%}...{% endif %}
-
-    **invalid**::
-
-        {% - if foo - %}...{% endif %}
-
-
-Escaping
---------
-
-It is sometimes desirable or even necessary to have Jinja ignore parts it
-would otherwise handle as variables or blocks.  For example if the default
-syntax is used and you want to use ``{{`` as raw string in the template and
-not start a variable you have to use a trick.
-
-The easiest way is to output the variable delimiter (``{{``) by using a
-variable expression::
-
-    {{ '{{' }}
-
-For bigger sections it makes sense to mark a block `raw`.  For example to
-put Jinja syntax as example into a template you can use this snippet::
-
-    {% raw %}
-        <ul>
-        {% for item in seq %}
-            <li>{{ item }}</li>
-        {% endfor %}
-        </ul>
-    {% endraw %}
-
-
-.. _line-statements:
-
-Line Statements
----------------
-
-If line statements are enabled by the application it's possible to mark a
-line as a statement.  For example if the line statement prefix is configured
-to ``#`` the following two examples are equivalent::
-
-    <ul>
-    # for item in seq
-        <li>{{ item }}</li>
-    # endfor
-    </ul>
-
-    <ul>
-    {% for item in seq %}
-        <li>{{ item }}</li>
-    {% endfor %}
-    </ul>
-
-The line statement prefix can appear anywhere on the line as long as no text
-precedes it.  For better readability statements that start a block (such as
-`for`, `if`, `elif` etc.) may end with a colon::
-
-    # for item in seq:
-        ...
-    # endfor
-
-
-.. admonition:: Note
-
-    Line statements can span multiple lines if there are open parentheses,
-    braces or brackets::
-
-        <ul>
-        # for href, caption in [('index.html', 'Index'),
-                                ('about.html', 'About')]:
-            <li><a href="{{ href }}">{{ caption }}</a></li>
-        # endfor
-        </ul>
-
-Since Jinja 2.2 line-based comments are available as well.  For example if
-the line-comment prefix is configured to be ``##`` everything from ``##`` to
-the end of the line is ignored (excluding the newline sign)::
-
-    # for item in seq:
-        <li>{{ item }}</li>     ## this comment is ignored
-    # endfor
-
-
-.. _template-inheritance:
-
-Template Inheritance
---------------------
-
-The most powerful part of Jinja is template inheritance. Template inheritance
-allows you to build a base "skeleton" template that contains all the common
-elements of your site and defines **blocks** that child templates can override.
-
-Sounds complicated but is very basic. It's easiest to understand it by starting
-with an example.
-
-
-Base Template
-~~~~~~~~~~~~~
-
-This template, which we'll call ``base.html``, defines a simple HTML skeleton
-document that you might use for a simple two-column page. It's the job of
-"child" templates to fill the empty blocks with content::
-
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-    <html lang="en">
-    <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        {% block head %}
-        <link rel="stylesheet" href="style.css" />
-        <title>{% block title %}{% endblock %} - My Webpage</title>
-        {% endblock %}
-    </head>
-    <body>
-        <div id="content">{% block content %}{% endblock %}</div>
-        <div id="footer">
-            {% block footer %}
-            &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
-            {% endblock %}
-        </div>
-    </body>
-
-In this example, the ``{% block %}`` tags define four blocks that child templates
-can fill in. All the `block` tag does is to tell the template engine that a
-child template may override those portions of the template.
-
-Child Template
-~~~~~~~~~~~~~~
-
-A child template might look like this::
-
-    {% extends "base.html" %}
-    {% block title %}Index{% endblock %}
-    {% block head %}
-        {{ super() }}
-        <style type="text/css">
-            .important { color: #336699; }
-        </style>
-    {% endblock %}
-    {% block content %}
-        <h1>Index</h1>
-        <p class="important">
-          Welcome on my awesome homepage.
-        </p>
-    {% endblock %}
-
-The ``{% extends %}`` tag is the key here. It tells the template engine that
-this template "extends" another template.  When the template system evaluates
-this template, first it locates the parent.  The extends tag should be the
-first tag in the template.  Everything before it is printed out normally and
-may cause confusion.  For details about this behavior and how to take
-advantage of it, see :ref:`null-master-fallback`.
-
-The filename of the template depends on the template loader.  For example the
-:class:`FileSystemLoader` allows you to access other templates by giving the
-filename.  You can access templates in subdirectories with an slash::
-
-    {% extends "layout/default.html" %}
-
-But this behavior can depend on the application embedding Jinja.  Note that
-since the child template doesn't define the ``footer`` block, the value from
-the parent template is used instead.
-
-You can't define multiple ``{% block %}`` tags with the same name in the
-same template.  This limitation exists because a block tag works in "both"
-directions.  That is, a block tag doesn't just provide a hole to fill - it
-also defines the content that fills the hole in the *parent*.  If there
-were two similarly-named ``{% block %}`` tags in a template, that template's
-parent wouldn't know which one of the blocks' content to use.
-
-If you want to print a block multiple times you can however use the special
-`self` variable and call the block with that name::
-
-    <title>{% block title %}{% endblock %}</title>
-    <h1>{{ self.title() }}</h1>
-    {% block body %}{% endblock %}
-
-
-Super Blocks
-~~~~~~~~~~~~
-
-It's possible to render the contents of the parent block by calling `super`.
-This gives back the results of the parent block::
-
-    {% block sidebar %}
-        <h3>Table Of Contents</h3>
-        ...
-        {{ super() }}
-    {% endblock %}
-
-
-Named Block End-Tags
-~~~~~~~~~~~~~~~~~~~~
-
-Jinja2 allows you to put the name of the block after the end tag for better
-readability::
-
-    {% block sidebar %}
-        {% block inner_sidebar %}
-            ...
-        {% endblock inner_sidebar %}
-    {% endblock sidebar %}
-
-However the name after the `endblock` word must match the block name.
-
-
-Block Nesting and Scope
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Blocks can be nested for more complex layouts.  However per default blocks
-may not access variables from outer scopes::
-
-    {% for item in seq %}
-        <li>{% block loop_item %}{{ item }}{% endblock %}</li>
-    {% endfor %}
-
-This example would output empty ``<li>`` items because `item` is unavailable
-inside the block.  The reason for this is that if the block is replaced by
-a child template a variable would appear that was not defined in the block or
-passed to the context.
-
-Starting with Jinja 2.2 you can explicitly specify that variables are
-available in a block by setting the block to "scoped" by adding the `scoped`
-modifier to a block declaration::
-
-    {% for item in seq %}
-        <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
-    {% endfor %}
-
-When overriding a block the `scoped` modifier does not have to be provided.
-
-
-Template Objects
-~~~~~~~~~~~~~~~~
-
-.. versionchanged:: 2.4
-
-If a template object was passed to the template context you can
-extend from that object as well.  Assuming the calling code passes
-a layout template as `layout_template` to the environment, this
-code works::
-
-    {% extends layout_template %}
-
-Previously the `layout_template` variable had to be a string with
-the layout template's filename for this to work.
-
-
-HTML Escaping
--------------
-
-When generating HTML from templates, there's always a risk that a variable will
-include characters that affect the resulting HTML.  There are two approaches:
-manually escaping each variable or automatically escaping everything by default.
-
-Jinja supports both, but what is used depends on the application configuration.
-The default configuaration is no automatic escaping for various reasons:
-
--   escaping everything except of safe values will also mean that Jinja is
-    escaping variables known to not include HTML such as numbers which is
-    a huge performance hit.
-
--   The information about the safety of a variable is very fragile.  It could
-    happen that by coercing safe and unsafe values the return value is double
-    escaped HTML.
-
-Working with Manual Escaping
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If manual escaping is enabled it's **your** responsibility to escape
-variables if needed.  What to escape?  If you have a variable that *may*
-include any of the following chars (``>``, ``<``, ``&``, or ``"``) you
-**have to** escape it unless the variable contains well-formed and trusted
-HTML.  Escaping works by piping the variable through the ``|e`` filter:
-``{{ user.username|e }}``.
-
-Working with Automatic Escaping
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When automatic escaping is enabled everything is escaped by default except
-for values explicitly marked as safe.  Those can either be marked by the
-application or in the template by using the `|safe` filter.  The main
-problem with this approach is that Python itself doesn't have the concept
-of tainted values so the information if a value is safe or unsafe can get
-lost.  If the information is lost escaping will take place which means that
-you could end up with double escaped contents.
-
-Double escaping is easy to avoid however, just rely on the tools Jinja2
-provides and don't use builtin Python constructs such as the string modulo
-operator.
-
-Functions returning template data (macros, `super`, `self.BLOCKNAME`) return
-safe markup always.
-
-String literals in templates with automatic escaping are considered unsafe
-too.  The reason for this is that the safe string is an extension to Python
-and not every library will work properly with it.
-
-
-List of Control Structures
---------------------------
-
-A control structure refers to all those things that control the flow of a
-program - conditionals (i.e. if/elif/else), for-loops, as well as things like
-macros and blocks.  Control structures appear inside ``{% ... %}`` blocks
-in the default syntax.
-
-For
-~~~
-
-Loop over each item in a sequence.  For example, to display a list of users
-provided in a variable called `users`::
-
-    <h1>Members</h1>
-    <ul>
-    {% for user in users %}
-      <li>{{ user.username|e }}</li>
-    {% endfor %}
-    </ul>
-
-Inside of a for loop block you can access some special variables:
-
-+-----------------------+---------------------------------------------------+
-| Variable              | Description                                       |
-+=======================+===================================================+
-| `loop.index`          | The current iteration of the loop. (1 indexed)    |
-+-----------------------+---------------------------------------------------+
-| `loop.index0`         | The current iteration of the loop. (0 indexed)    |
-+-----------------------+---------------------------------------------------+
-| `loop.revindex`       | The number of iterations from the end of the loop |
-|                       | (1 indexed)                                       |
-+-----------------------+---------------------------------------------------+
-| `loop.revindex0`      | The number of iterations from the end of the loop |
-|                       | (0 indexed)                                       |
-+-----------------------+---------------------------------------------------+
-| `loop.first`          | True if first iteration.                          |
-+-----------------------+---------------------------------------------------+
-| `loop.last`           | True if last iteration.                           |
-+-----------------------+---------------------------------------------------+
-| `loop.length`         | The number of items in the sequence.              |
-+-----------------------+---------------------------------------------------+
-| `loop.cycle`          | A helper function to cycle between a list of      |
-|                       | sequences.  See the explanation below.            |
-+-----------------------+---------------------------------------------------+
-
-Within a for-loop, it's possible to cycle among a list of strings/variables
-each time through the loop by using the special `loop.cycle` helper::
-
-    {% for row in rows %}
-        <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
-    {% endfor %}
-
-With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound
-cycling.  For more information have a look at the :ref:`builtin-globals`.
-
-.. _loop-filtering:
-
-Unlike in Python it's not possible to `break` or `continue` in a loop.  You
-can however filter the sequence during iteration which allows you to skip
-items.  The following example skips all the users which are hidden::
-
-    {% for user in users if not user.hidden %}
-        <li>{{ user.username|e }}</li>
-    {% endfor %}
-
-The advantage is that the special `loop` variable will count correctly thus
-not counting the users not iterated over.
-
-If no iteration took place because the sequence was empty or the filtering
-removed all the items from the sequence you can render a replacement block
-by using `else`::
-
-    <ul>
-    {% for user in users %}
-        <li>{{ user.username|e }}</li>
-    {% else %}
-        <li><em>no users found</em></li>
-    {% endfor %}
-    </ul>
-
-It is also possible to use loops recursively.  This is useful if you are
-dealing with recursive data such as sitemaps.  To use loops recursively you
-basically have to add the `recursive` modifier to the loop definition and
-call the `loop` variable with the new iterable where you want to recurse.
-
-The following example implements a sitemap with recursive loops::
-
-    <ul class="sitemap">
-    {%- for item in sitemap recursive %}
-        <li><a href="{{ item.href|e }}">{{ item.title }}</a>
-        {%- if item.children -%}
-            <ul class="submenu">{{ loop(item.children) }}</ul>
-        {%- endif %}</li>
-    {%- endfor %}
-    </ul>
-
-
-If
-~~
-
-The `if` statement in Jinja is comparable with the if statements of Python.
-In the simplest form you can use it to test if a variable is defined, not
-empty or not false::
-
-    {% if users %}
-    <ul>
-    {% for user in users %}
-        <li>{{ user.username|e }}</li>
-    {% endfor %}
-    </ul>
-    {% endif %}
-
-For multiple branches `elif` and `else` can be used like in Python.  You can
-use more complex :ref:`expressions` there too::
-
-    {% if kenny.sick %}
-        Kenny is sick.
-    {% elif kenny.dead %}
-        You killed Kenny!  You bastard!!!
-    {% else %}
-        Kenny looks okay --- so far
-    {% endif %}
-
-If can also be used as :ref:`inline expression <if-expression>` and for
-:ref:`loop filtering <loop-filtering>`.
-
-
-Macros
-~~~~~~
-
-Macros are comparable with functions in regular programming languages.  They
-are useful to put often used idioms into reusable functions to not repeat
-yourself.
-
-Here a small example of a macro that renders a form element::
-
-    {% macro input(name, value='', type='text', size=20) -%}
-        <input type="{{ type }}" name="{{ name }}" value="{{
-            value|e }}" size="{{ size }}">
-    {%- endmacro %}
-
-The macro can then be called like a function in the namespace::
-
-    <p>{{ input('username') }}</p>
-    <p>{{ input('password', type='password') }}</p>
-
-If the macro was defined in a different template you have to
-:ref:`import <import>` it first.
-
-Inside macros you have access to three special variables:
-
-`varargs`
-    If more positional arguments are passed to the macro than accepted by the
-    macro they end up in the special `varargs` variable as list of values.
-
-`kwargs`
-    Like `varargs` but for keyword arguments.  All unconsumed keyword
-    arguments are stored in this special variable.
-
-`caller`
-    If the macro was called from a :ref:`call<call>` tag the caller is stored
-    in this variable as macro which can be called.
-
-Macros also expose some of their internal details.  The following attributes
-are available on a macro object:
-
-`name`
-    The name of the macro.  ``{{ input.name }}`` will print ``input``.
-
-`arguments`
-    A tuple of the names of arguments the macro accepts.
-
-`defaults`
-    A tuple of default values.
-
-`catch_kwargs`
-    This is `true` if the macro accepts extra keyword arguments (ie: accesses
-    the special `kwargs` variable).
-
-`catch_varargs`
-    This is `true` if the macro accepts extra positional arguments (ie:
-    accesses the special `varargs` variable).
-
-`caller`
-    This is `true` if the macro accesses the special `caller` variable and may
-    be called from a :ref:`call<call>` tag.
-
-If a macro name starts with an underscore it's not exported and can't
-be imported.
-
-
-.. _call:
-
-Call
-~~~~
-
-In some cases it can be useful to pass a macro to another macro.  For this
-purpose you can use the special `call` block.  The following example shows
-a macro that takes advantage of the call functionality and how it can be
-used::
-
-    {% macro render_dialog(title, class='dialog') -%}
-        <div class="{{ class }}">
-            <h2>{{ title }}</h2>
-            <div class="contents">
-                {{ caller() }}
-            </div>
-        </div>
-    {%- endmacro %}
-
-    {% call render_dialog('Hello World') %}
-        This is a simple dialog rendered by using a macro and
-        a call block.
-    {% endcall %}
-
-It's also possible to pass arguments back to the call block.  This makes it
-useful as replacement for loops.  Generally speaking a call block works
-exactly like an macro, just that it doesn't have a name.
-
-Here an example of how a call block can be used with arguments::
-
-    {% macro dump_users(users) -%}
-        <ul>
-        {%- for user in users %}
-            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
-        {%- endfor %}
-        </ul>
-    {%- endmacro %}
-
-    {% call(user) dump_users(list_of_user) %}
-        <dl>
-            <dl>Realname</dl>
-            <dd>{{ user.realname|e }}</dd>
-            <dl>Description</dl>
-            <dd>{{ user.description }}</dd>
-        </dl>
-    {% endcall %}
-
-
-Filters
-~~~~~~~
-
-Filter sections allow you to apply regular Jinja2 filters on a block of
-template data.  Just wrap the code in the special `filter` section::
-
-    {% filter upper %}
-        This text becomes uppercase
-    {% endfilter %}
-
-
-Assignments
-~~~~~~~~~~~
-
-Inside code blocks you can also assign values to variables.  Assignments at
-top level (outside of blocks, macros or loops) are exported from the template
-like top level macros and can be imported by other templates.
-
-Assignments use the `set` tag and can have multiple targets::
-
-    {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
-    {% set key, value = call_something() %}
-
-
-Extends
-~~~~~~~
-
-The `extends` tag can be used to extend a template from another one.  You
-can have multiple of them in a file but only one of them may be executed
-at the time.  See the section about :ref:`template-inheritance` above.
-
-
-Block
-~~~~~
-
-Blocks are used for inheritance and act as placeholders and replacements
-at the same time.  They are documented in detail as part of the section
-about :ref:`template-inheritance`.
-
-
-Include
-~~~~~~~
-
-The `include` statement is useful to include a template and return the
-rendered contents of that file into the current namespace::
-
-    {% include 'header.html' %}
-        Body
-    {% include 'footer.html' %}
-
-Included templates have access to the variables of the active context by
-default.  For more details about context behavior of imports and includes
-see :ref:`import-visibility`.
-
-From Jinja 2.2 onwards you can mark an include with ``ignore missing`` in
-which case Jinja will ignore the statement if the template to be ignored
-does not exist.  When combined with ``with`` or ``without context`` it has
-to be placed *before* the context visibility statement.  Here some valid
-examples::
-
-    {% include "sidebar.html" ignore missing %}
-    {% include "sidebar.html" ignore missing with context %}
-    {% include "sidebar.html" ignore missing without context %}
-
-.. versionadded:: 2.2
-
-You can also provide a list of templates that are checked for existence
-before inclusion.  The first template that exists will be included.  If
-`ignore missing` is given, it will fall back to rendering nothing if
-none of the templates exist, otherwise it will raise an exception.
-
-Example::
-
-    {% include ['page_detailed.html', 'page.html'] %}
-    {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
-
-.. versionchanged:: 2.4
-   If a template object was passed to the template context you can
-   include that object using `include`.
-
-.. _import:
-
-Import
-~~~~~~
-
-Jinja2 supports putting often used code into macros.  These macros can go into
-different templates and get imported from there.  This works similar to the
-import statements in Python.  It's important to know that imports are cached
-and imported templates don't have access to the current template variables,
-just the globals by defualt.  For more details about context behavior of
-imports and includes see :ref:`import-visibility`.
-
-There are two ways to import templates.  You can import the complete template
-into a variable or request specific macros / exported variables from it.
-
-Imagine we have a helper module that renders forms (called `forms.html`)::
-
-    {% macro input(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 %}
-
-The easiest and most flexible is importing the whole module into a variable.
-That way you can access the attributes::
-
-    {% import 'forms.html' as forms %}
-    <dl>
-        <dt>Username</dt>
-        <dd>{{ forms.input('username') }}</dd>
-        <dt>Password</dt>
-        <dd>{{ forms.input('password', type='password') }}</dd>
-    </dl>
-    <p>{{ forms.textarea('comment') }}</p>
-
-
-Alternatively you can import names from the template into the current
-namespace::
-
-    {% from 'forms.html' import input as input_field, textarea %}
-    <dl>
-        <dt>Username</dt>
-        <dd>{{ input_field('username') }}</dd>
-        <dt>Password</dt>
-        <dd>{{ input_field('password', type='password') }}</dd>
-    </dl>
-    <p>{{ textarea('comment') }}</p>
-
-Macros and variables starting with one ore more underscores are private and
-cannot be imported.
-
-.. versionchanged:: 2.4
-   If a template object was passed to the template context you can
-   import from that object.
-
-
-.. _import-visibility:
-
-Import Context Behavior
------------------------
-
-Per default included templates are passed the current context and imported
-templates not.  The reason for this is that imports unlike includes are
-cached as imports are often used just as a module that holds macros.
-
-This however can be changed of course explicitly.  By adding `with context`
-or `without context` to the import/include directive the current context
-can be passed to the template and caching is disabled automatically.
-
-Here two examples::
-
-    {% from 'forms.html' import input with context %}
-    {% include 'header.html' without context %}
-
-.. admonition:: Note
-
-    In Jinja 2.0 the context that was passed to the included template
-    did not include variables defined in the template.  As a matter of
-    fact this did not work::
-
-        {% for box in boxes %}
-            {% include "render_box.html" %}
-        {% endfor %}
-
-    The included template ``render_box.html`` is not able to access
-    `box` in Jinja 2.0, but in Jinja 2.1.
-
-
-.. _expressions:
-
-Expressions
------------
-
-Jinja allows basic expressions everywhere.  These work very similar to regular
-Python and even if you're not working with Python you should feel comfortable
-with it.
-
-Literals
-~~~~~~~~
-
-The simplest form of expressions are literals.  Literals are representations
-for Python objects such as strings and numbers.  The following literals exist:
-
-"Hello World":
-    Everything between two double or single quotes is a string.  They are
-    useful whenever you need a string in the template (for example as
-    arguments to function calls, filters or just to extend or include a
-    template).
-
-42 / 42.23:
-    Integers and floating point numbers are created by just writing the
-    number down.  If a dot is present the number is a float, otherwise an
-    integer.  Keep in mind that for Python ``42`` and ``42.0`` is something
-    different.
-
-['list', 'of', 'objects']:
-    Everything between two brackets is a list.  Lists are useful to store
-    sequential data in or to iterate over them.  For example you can easily
-    create a list of links using lists and tuples with a for loop::
-
-        <ul>
-        {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
-                                 ('downloads.html', 'Downloads')] %}
-            <li><a href="{{ href }}">{{ caption }}</a></li>
-        {% endfor %}
-        </ul>
-
-('tuple', 'of', 'values'):
-    Tuples are like lists, just that you can't modify them.  If the tuple
-    only has one item you have to end it with a comma.  Tuples are usually
-    used to represent items of two or more elements.  See the example above
-    for more details.
-
-{'dict': 'of', 'key': 'and', 'value': 'pairs'}:
-    A dict in Python is a structure that combines keys and values.  Keys must
-    be unique and always have exactly one value.  Dicts are rarely used in
-    templates, they are useful in some rare cases such as the :func:`xmlattr`
-    filter.
-
-true / false:
-    true is always true and false is always false.
-
-.. admonition:: Note
-
-    The special constants `true`, `false` and `none` are indeed lowercase.
-    Because that caused confusion in the past, when writing `True` expands
-    to an undefined variable that is considered false, all three of them can
-    be written in title case too (`True`, `False`, and `None`).  However for
-    consistency (all Jinja identifiers are lowercase) you should use the
-    lowercase versions.
-
-Math
-~~~~
-
-Jinja allows you to calculate with values.  This is rarely useful in templates
-but exists for completeness' sake.  The following operators are supported:
-
-\+
-    Adds two objects together.  Usually the objects are numbers but if both are
-    strings or lists you can concatenate them this way.  This however is not
-    the preferred way to concatenate strings!  For string concatenation have
-    a look at the ``~`` operator.  ``{{ 1 + 1 }}`` is ``2``.
-
-\-
-    Substract the second number from the first one.  ``{{ 3 - 2 }}`` is ``1``.
-
-/
-    Divide two numbers.  The return value will be a floating point number.
-    ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
-
-//
-    Divide two numbers and return the truncated integer result.
-    ``{{ 20 / 7 }}`` is ``2``.
-
-%
-    Calculate the remainder of an integer division.  ``{{ 11 % 7 }}`` is ``4``.
-
-\*
-    Multiply the left operand with the right one.  ``{{ 2 * 2 }}`` would
-    return ``4``.  This can also be used to repeat a string multiple times.
-    ``{{ '=' * 80 }}`` would print a bar of 80 equal signs.
-
-\**
-    Raise the left operand to the power of the right operand.  ``{{ 2**3 }}``
-    would return ``8``.
-
-Comparisons
-~~~~~~~~~~~
-
-==
-    Compares two objects for equality.
-
-!=
-    Compares two objects for inequality.
-
->
-    `true` if the left hand side is greater than the right hand side.
-
->=
-    `true` if the left hand side is greater or equal to the right hand side.
-
-<
-    `true` if the left hand side is lower than the right hand side.
-
-<=
-    `true` if the left hand side is lower or equal to the right hand side.
-
-Logic
-~~~~~
-
-For `if` statements, `for` filtering or `if` expressions it can be useful to
-combine multiple expressions:
-
-and
-    Return true if the left and the right operand is true.
-
-or
-    Return true if the left or the right operand is true.
-
-not
-    negate a statement (see below).
-
-(expr)
-    group an expression.
-
-.. admonition:: Note
-
-    The ``is`` and ``in`` operators support negation using an infix notation
-    too: ``foo is not bar`` and ``foo not in bar`` instead of ``not foo is bar``
-    and ``not foo in bar``.  All other expressions require a prefix notation:
-    ``not (foo and bar).``
-
-
-Other Operators
-~~~~~~~~~~~~~~~
-
-The following operators are very useful but don't fit into any of the other
-two categories:
-
-in
-    Perform sequence / mapping containment test.  Returns true if the left
-    operand is contained in the right.  ``{{ 1 in [1, 2, 3] }}`` would for
-    example return true.
-
-is
-    Performs a :ref:`test <tests>`.
-
-\|
-    Applies a :ref:`filter <filters>`.
-
-~
-    Converts all operands into strings and concatenates them.
-    ``{{ "Hello " ~ name ~ "!" }}`` would return (assuming `name` is
-    ``'John'``) ``Hello John!``.
-
-()
-    Call a callable: ``{{ post.render() }}``.  Inside of the parentheses you
-    can use positional arguments and keyword arguments like in python:
-    ``{{ post.render(user, full=true) }}``.
-
-. / []
-    Get an attribute of an object.  (See :ref:`variables`)
-
-
-.. _if-expression:
-
-If Expression
-~~~~~~~~~~~~~
-
-It is also possible to use inline `if` expressions.  These are useful in some
-situations.  For example you can use this to extend from one template if a
-variable is defined, otherwise from the default layout template::
-
-    {% extends layout_template if layout_template is defined else 'master.html' %}
-
-The general syntax is ``<do something> if <something is true> else <do
-something else>``.
-
-The `else` part is optional.  If not provided the else block implicitly
-evaluates into an undefined object::
-
-    {{ '[%s]' % page.title if page.title }}
-
-
-.. _builtin-filters:
-
-List of Builtin Filters
------------------------
-
-.. jinjafilters::
-
-
-.. _builtin-tests:
-
-List of Builtin Tests
----------------------
-
-.. jinjatests::
-
-.. _builtin-globals:
-
-List of Global Functions
-------------------------
-
-The following functions are available in the global scope by default:
-
-.. function:: range([start,] stop[, step])
-
-    Return a list containing an arithmetic progression of integers.
-    range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
-    When step is given, it specifies the increment (or decrement).
-    For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
-    These are exactly the valid indices for a list of 4 elements.
-
-    This is useful to repeat a template block multiple times for example
-    to fill a list.  Imagine you have 7 users in the list but you want to
-    render three empty items to enforce a height with CSS::
-
-        <ul>
-        {% for user in users %}
-            <li>{{ user.username }}</li>
-        {% endfor %}
-        {% for number in range(10 - users|count) %}
-            <li class="empty"><span>...</span></li>
-        {% endfor %}
-        </ul>
-
-.. function:: lipsum(n=5, html=True, min=20, max=100)
-
-    Generates some lorem ipsum for the template.  Per default five paragraphs
-    with HTML are generated each paragraph between 20 and 100 words.  If html
-    is disabled regular text is returned.  This is useful to generate simple
-    contents for layout testing.
-
-.. function:: dict(\**items)
-
-    A convenient alternative to dict literals.  ``{'foo': 'bar'}`` is the same
-    as ``dict(foo='bar')``.
-
-.. class:: cycler(\*items)
-
-    The cycler allows you to cycle among values similar to how `loop.cycle`
-    works.  Unlike `loop.cycle` however you can use this cycler outside of
-    loops or over multiple loops.
-
-    This is for example very useful if you want to show a list of folders and
-    files, with the folders on top, but both in the same list with alternating
-    row colors.
-
-    The following example shows how `cycler` can be used::
-
-        {% set row_class = cycler('odd', 'even') %}
-        <ul class="browser">
-        {% for folder in folders %}
-          <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
-        {% endfor %}
-        {% for filename in files %}
-          <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
-        {% endfor %}
-        </ul>
-
-    A cycler has the following attributes and methods:
-
-    .. method:: reset()
-
-        Resets the cycle to the first item.
-
-    .. method:: next()
-
-        Goes one item a head and returns the then current item.
-
-    .. attribute:: current
-
-        Returns the current item.
-    
-    **new in Jinja 2.1**
-
-.. class:: joiner(sep=', ')
-
-    A tiny helper that can be use to "join" multiple sections.  A joiner is
-    passed a string and will return that string every time it's calld, except
-    the first time in which situation it returns an empty string.  You can
-    use this to join things::
-
-        {% set pipe = joiner("|") %}
-        {% if categories %} {{ pipe() }}
-            Categories: {{ categories|join(", ") }}
-        {% endif %}
-        {% if author %} {{ pipe() }}
-            Author: {{ author() }}
-        {% endif %}
-        {% if can_edit %} {{ pipe() }}
-            <a href="?action=edit">Edit</a>
-        {% endif %}
-
-    **new in Jinja 2.1**
-
-
-Extensions
-----------
-
-The following sections cover the built-in Jinja2 extensions that may be
-enabled by the application.  The application could also provide further
-extensions not covered by this documentation.  In that case there should
-be a separate document explaining the extensions.
-
-.. _i18n-in-templates:
-
-i18n
-~~~~
-
-If the i18n extension is enabled it's possible to mark parts in the template
-as translatable.  To mark a section as translatable you can use `trans`::
-
-    <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
-
-To translate a template expression --- say, using template filters or just
-accessing an attribute of an object --- you need to bind the expression to a
-name for use within the translation block::
-
-    <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
-
-If you need to bind more than one expression inside a `trans` tag, separate
-the pieces with a comma (``,``)::
-
-    {% trans book_title=book.title, author=author.name %}
-    This is {{ book_title }} by {{ author }}
-    {% endtrans %}
-
-Inside trans tags no statements are allowed, only variable tags are.
-
-To pluralize, specify both the singular and plural forms with the `pluralize`
-tag, which appears between `trans` and `endtrans`::
-
-    {% trans count=list|length %}
-    There is {{ count }} {{ name }} object.
-    {% pluralize %}
-    There are {{ count }} {{ name }} objects.
-    {% endtrans %}
-
-Per default the first variable in a block is used to determine the correct
-singular or plural form.  If that doesn't work out you can specify the name
-which should be used for pluralizing by adding it as parameter to `pluralize`::
-
-    {% trans ..., user_count=users|length %}...
-    {% pluralize user_count %}...{% endtrans %}
-
-It's also possible to translate strings in expressions.  For that purpose
-three functions exist:
-
-_   `gettext`: translate a single string
--   `ngettext`: translate a pluralizable string
--   `_`: alias for `gettext`
-
-For example you can print a translated string easily this way::
-
-    {{ _('Hello World!') }}
-
-To use placeholders you can use the `format` filter::
-
-    {{ _('Hello %(user)s!')|format(user=user.username) }}
-
-For multiple placeholders always use keyword arguments to `format` as other
-languages may not use the words in the same order.
-
-.. versionchanged:: 2.5
-
-If newstyle gettext calls are activated (:ref:`newstyle-gettext`), using
-placeholders is a lot easier:
-
-.. sourcecode:: html+jinja
-
-    {{ gettext('Hello World!') }}
-    {{ gettext('Hello %(name)s!', name='World') }}
-    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
-
-Note that the `ngettext` function's format string automatically recieves
-the count as `num` parameter additionally to the regular parameters.
-
-
-Expression Statement
-~~~~~~~~~~~~~~~~~~~~
-
-If the expression-statement extension is loaded a tag called `do` is available
-that works exactly like the regular variable expression (``{{ ... }}``) just
-that it doesn't print anything.  This can be used to modify lists::
-
-    {% do navigation.append('a string') %}
-
-
-Loop Controls
-~~~~~~~~~~~~~
-
-If the application enables the :ref:`loopcontrols-extension` it's possible to
-use `break` and `continue` in loops.  When `break` is reached, the loop is
-terminated, if `continue` is eached the processing is stopped and continues
-with the next iteration.
-
-Here a loop that skips every second item::
-
-    {% for user in users %}
-        {%- if loop.index is even %}{% continue %}{% endif %}
-        ...
-    {% endfor %}
-
-Likewise a look that stops processing after the 10th iteration::
-
-    {% for user in users %}
-        {%- if loop.index >= 10 %}{% break %}{% endif %}
-    {%- endfor %}
-
-
-With Statement
-~~~~~~~~~~~~~~
-
-.. versionadded:: 2.3
-
-If the application enables the :ref:`with-extension` it is possible to
-use the `with` keyword in templates.  This makes it possible to create
-a new inner scope.  Variables set within this scope are not visible
-outside of the scope.
-
-With in a nutshell::
-
-    {% with %}
-        {% set foo = 42 %}
-        {{ foo }}           foo is 42 here
-    {% endwith %}
-    foo is not visible here any longer
-
-Because it is common to set variables at the beginning of the scope
-you can do that within the with statement.  The following two examples
-are equivalent::
-
-    {% with foo = 42 %}
-        {{ foo }}
-    {% endwith %}
-
-    {% with %}
-        {% set foo = 42 %}
-        {{ foo }}
-    {% endwith %}
-
-.. _autoescape-overrides:
-
-Autoescape Extension
---------------------
-
-.. versionadded:: 2.4
-
-If the application enables the :ref:`autoescape-extension` one can
-activate and deactivate the autoescaping from within the templates.
-
-Example::
-
-    {% autoescape true %}
-        Autoescaping is active within this block
-    {% endautoescape %}
-
-    {% autoescape false %}
-        Autoescaping is inactive within this block
-    {% endautoescape %}
-
-After the `endautoescape` the behavior is reverted to what it was before.

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/tricks.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/tricks.rst b/ambari-common/src/main/python/jinja2/docs/tricks.rst
deleted file mode 100644
index 566575e..0000000
--- a/ambari-common/src/main/python/jinja2/docs/tricks.rst
+++ /dev/null
@@ -1,100 +0,0 @@
-Tips and Tricks
-===============
-
-.. highlight:: html+jinja
-
-This part of the documentation shows some tips and tricks for Jinja2
-templates.
-
-
-.. _null-master-fallback:
-
-Null-Master Fallback
---------------------
-
-Jinja2 supports dynamic inheritance and does not distinguish between parent
-and child template as long as no `extends` tag is visited.  While this leads
-to the surprising behavior that everything before the first `extends` tag
-including whitespace is printed out instead of being igored, it can be used
-for a neat trick.
-
-Usually child templates extend from one template that adds a basic HTML
-skeleton.  However it's possible put the `extends` tag into an `if` tag to
-only extend from the layout template if the `standalone` variable evaluates
-to false which it does per default if it's not defined.  Additionally a very
-basic skeleton is added to the file so that if it's indeed rendered with
-`standalone` set to `True` a very basic HTML skeleton is added::
-
-    {% if not standalone %}{% extends 'master.html' %}{% endif -%}
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-    <title>{% block title %}The Page Title{% endblock %}</title>
-    <link rel="stylesheet" href="style.css" type="text/css">
-    {% block body %}
-      <p>This is the page body.</p>
-    {% endblock %}
-
-
-Alternating Rows
-----------------
-
-If you want to have different styles for each row of a table or
-list you can use the `cycle` method on the `loop` object::
-
-    <ul>
-    {% for row in rows %}
-      <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
-    {% endfor %}
-    </ul>
-
-`cycle` can take an unlimited amount of strings.  Each time this
-tag is encountered the next item from the list is rendered.
-
-
-Highlighting Active Menu Items
-------------------------------
-
-Often you want to have a navigation bar with an active navigation
-item.  This is really simple to achieve.  Because assignments outside
-of `block`\s in child templates are global and executed before the layout
-template is evaluated it's possible to define the active menu item in the
-child template::
-
-    {% extends "layout.html" %}
-    {% set active_page = "index" %}
-
-The layout template can then access `active_page`.  Additionally it makes
-sense to defined a default for that variable::
-
-    {% set navigation_bar = [
-        ('/', 'index', 'Index'),
-        ('/downloads/', 'downloads', 'Downloads'),
-        ('/about/', 'about', 'About')
-    ] -%}
-    {% set active_page = active_page|default('index') -%}
-    ...
-    <ul id="navigation">
-    {% for href, id, caption in navigation_bar %}
-      <li{% if id == active_page %} class="active"{% endif
-      %}><a href="{{ href|e }}">{{ caption|e }}</a>/li>
-    {% endfor %}
-    </ul>
-    ...
-
-.. _accessing-the-parent-loop:
-
-Accessing the parent Loop
--------------------------
-
-The special `loop` variable always points to the innermost loop.  If it's
-desired to have access to an outer loop it's possible to alias it::
-
-    <table>
-    {% for row in table %}
-      <tr>
-      {% set rowloop = loop %}
-      {% for cell in row %}
-        <td id="cell-{{ rowloop.index }}-{{ loop.index }}>{{ cell }}</td>
-      {% endfor %}
-      </tr>
-    {% endfor %}
-    </table>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/cycle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/cycle.py b/ambari-common/src/main/python/jinja2/examples/basic/cycle.py
deleted file mode 100644
index 73dd632..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/cycle.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from jinja2 import Environment
-
-
-env = Environment(line_statement_prefix="#", variable_start_string="${", variable_end_string="}")
-
-
-print env.from_string("""\
-<ul>
-# for item in range(10)
-    <li class="${loop.cycle('odd', 'even')}">${item}</li>
-# endfor
-</ul>\
-""").render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/debugger.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/debugger.py b/ambari-common/src/main/python/jinja2/examples/basic/debugger.py
deleted file mode 100644
index 4291ff7..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/debugger.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from jinja2 import Environment
-from jinja2.loaders import FileSystemLoader
-
-env = Environment(loader=FileSystemLoader('templates'))
-
-tmpl = env.get_template('broken.html')
-print tmpl.render(seq=[3, 2, 4, 5, 3, 2, 0, 2, 1])

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py b/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py
deleted file mode 100644
index aa687c8..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from jinja2 import Environment
-from jinja2.loaders import DictLoader
-
-
-env = Environment(loader=DictLoader({
-'a': '''[A[{% block body %}{% endblock %}]]''',
-'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''',
-'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}'''
-}))
-
-
-print env.get_template('c').render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html b/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html
deleted file mode 100644
index 294d5c9..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% from 'subbroken.html' import may_break %}
-<ul>
-{% for item in seq %}
-  <li>{{ may_break(item) }}</li>
-{% endfor %}
-</ul>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html b/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html
deleted file mode 100644
index 245eb7e..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{% macro may_break(item) -%}
-  [{{ item / 0 }}]
-{%- endmacro %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/test.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/test.py b/ambari-common/src/main/python/jinja2/examples/basic/test.py
deleted file mode 100644
index b62c84f..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/test.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from jinja2 import Environment
-from jinja2.loaders import DictLoader
-
-env = Environment(loader=DictLoader({
-'child.html': u'''\
-{% extends master_layout or 'master.html' %}
-{% include helpers = 'helpers.html' %}
-{% macro get_the_answer() %}42{% endmacro %}
-{% title = 'Hello World' %}
-{% block body %}
-    {{ get_the_answer() }}
-    {{ helpers.conspirate() }}
-{% endblock %}
-''',
-'master.html': u'''\
-<!doctype html>
-<title>{{ title }}</title>
-{% block body %}{% endblock %}
-''',
-'helpers.html': u'''\
-{% macro conspirate() %}23{% endmacro %}
-'''
-}))
-
-
-tmpl = env.get_template("child.html")
-print tmpl.render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py b/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py
deleted file mode 100644
index c9e8f95..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from jinja2 import Environment
-
-
-env = Environment(line_statement_prefix='%', variable_start_string="${", variable_end_string="}")
-tmpl = env.from_string("""\
-% macro foo()
-    ${caller(42)}
-% endmacro
-<ul>
-% for item in seq
-    <li>${item}</li>
-% endfor
-</ul>
-% call(var) foo()
-    [${var}]
-% endcall
-% filter escape
-    <hello world>
-    % for item in [1, 2, 3]
-      -  ${item}
-    % endfor
-% endfilter
-""")
-
-print tmpl.render(seq=range(10))

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py b/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py
deleted file mode 100644
index 49c2efc..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from jinja2 import Environment
-
-tmpl = Environment().from_string("""\
-<ul>
-{%- for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if item % 2 == 0 %}
-    <li>{{ loop.index }} / {{ loop.length }}: {{ item }}</li>
-{%- endfor %}
-</ul>
-if condition: {{ 1 if foo else 0 }}
-""")
-
-print tmpl.render(foo=True)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/basic/translate.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/translate.py b/ambari-common/src/main/python/jinja2/examples/basic/translate.py
deleted file mode 100644
index 3358765..0000000
--- a/ambari-common/src/main/python/jinja2/examples/basic/translate.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from jinja2 import Environment
-
-print Environment(extensions=['jinja2.i18n.TransExtension']).from_string("""\
-{% trans %}Hello {{ user }}!{% endtrans %}
-{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
-""").render(user="someone")

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/bench.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/bench.py b/ambari-common/src/main/python/jinja2/examples/bench.py
deleted file mode 100644
index c648dc6..0000000
--- a/ambari-common/src/main/python/jinja2/examples/bench.py
+++ /dev/null
@@ -1,433 +0,0 @@
-"""\
-    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 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/658360a5/ambari-common/src/main/python/jinja2/examples/profile.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/profile.py b/ambari-common/src/main/python/jinja2/examples/profile.py
deleted file mode 100644
index 0c907ae..0000000
--- a/ambari-common/src/main/python/jinja2/examples/profile.py
+++ /dev/null
@@ -1,52 +0,0 @@
-try:
-    from cProfile import Profile
-except ImportError:
-    from profile import Profile
-from pstats import Stats
-from 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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html
deleted file mode 100644
index 9c4f710..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html
+++ /dev/null
@@ -1 +0,0 @@
-<form action="{{ action }}" method="{{ method }}">{{ body }}</form>

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

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

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html
deleted file mode 100644
index 6f620bb..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% 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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html
deleted file mode 100644
index 60039ce..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py b/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py
deleted file mode 100644
index 9e9fa6c..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- 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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html b/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html
deleted file mode 100644
index ecc6dc4..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html
deleted file mode 100644
index 70f697d..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<?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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html
deleted file mode 100644
index b12aec4..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html b/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html
deleted file mode 100644
index 89976aa..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% 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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html
deleted file mode 100644
index b006d05..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% 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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html
deleted file mode 100644
index 755789e..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html b/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html
deleted file mode 100644
index a0290eb..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<%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>


[17/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py
deleted file mode 100644
index 804070c..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py
+++ /dev/null
@@ -1,901 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.nodes
-    ~~~~~~~~~~~~
-
-    This module implements additional nodes derived from the ast base node.
-
-    It also provides some node tree helper functions like `in_lineno` and
-    `get_nodes` used by the parser and translator in order to normalize
-    python and jinja nodes.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import operator
-from itertools import chain, izip
-from collections import deque
-from ambari_jinja2.utils import Markup, MethodType, FunctionType
-
-
-#: the types we support for context functions
-_context_function_types = (FunctionType, MethodType)
-
-
-_binop_to_func = {
-    '*':        operator.mul,
-    '/':        operator.truediv,
-    '//':       operator.floordiv,
-    '**':       operator.pow,
-    '%':        operator.mod,
-    '+':        operator.add,
-    '-':        operator.sub
-}
-
-_uaop_to_func = {
-    'not':      operator.not_,
-    '+':        operator.pos,
-    '-':        operator.neg
-}
-
-_cmpop_to_func = {
-    'eq':       operator.eq,
-    'ne':       operator.ne,
-    'gt':       operator.gt,
-    'gteq':     operator.ge,
-    'lt':       operator.lt,
-    'lteq':     operator.le,
-    'in':       lambda a, b: a in b,
-    'notin':    lambda a, b: a not in b
-}
-
-
-class Impossible(Exception):
-    """Raised if the node could not perform a requested action."""
-
-
-class NodeType(type):
-    """A metaclass for nodes that handles the field and attribute
-    inheritance.  fields and attributes from the parent class are
-    automatically forwarded to the child."""
-
-    def __new__(cls, name, bases, d):
-        for attr in 'fields', 'attributes':
-            storage = []
-            storage.extend(getattr(bases[0], attr, ()))
-            storage.extend(d.get(attr, ()))
-            assert len(bases) == 1, 'multiple inheritance not allowed'
-            assert len(storage) == len(set(storage)), 'layout conflict'
-            d[attr] = tuple(storage)
-        d.setdefault('abstract', False)
-        return type.__new__(cls, name, bases, d)
-
-
-class EvalContext(object):
-    """Holds evaluation time information.  Custom attributes can be attached
-    to it in extensions.
-    """
-
-    def __init__(self, environment, template_name=None):
-        if callable(environment.autoescape):
-            self.autoescape = environment.autoescape(template_name)
-        else:
-            self.autoescape = environment.autoescape
-        self.volatile = False
-
-    def save(self):
-        return self.__dict__.copy()
-
-    def revert(self, old):
-        self.__dict__.clear()
-        self.__dict__.update(old)
-
-
-def get_eval_context(node, ctx):
-    if ctx is None:
-        if node.environment is None:
-            raise RuntimeError('if no eval context is passed, the '
-                               'node must have an attached '
-                               'environment.')
-        return EvalContext(node.environment)
-    return ctx
-
-
-class Node(object):
-    """Baseclass for all Jinja2 nodes.  There are a number of nodes available
-    of different types.  There are three major types:
-
-    -   :class:`Stmt`: statements
-    -   :class:`Expr`: expressions
-    -   :class:`Helper`: helper nodes
-    -   :class:`Template`: the outermost wrapper node
-
-    All nodes have fields and attributes.  Fields may be other nodes, lists,
-    or arbitrary values.  Fields are passed to the constructor as regular
-    positional arguments, attributes as keyword arguments.  Each node has
-    two attributes: `lineno` (the line number of the node) and `environment`.
-    The `environment` attribute is set at the end of the parsing process for
-    all nodes automatically.
-    """
-    __metaclass__ = NodeType
-    fields = ()
-    attributes = ('lineno', 'environment')
-    abstract = True
-
-    def __init__(self, *fields, **attributes):
-        if self.abstract:
-            raise TypeError('abstract nodes are not instanciable')
-        if fields:
-            if len(fields) != len(self.fields):
-                if not self.fields:
-                    raise TypeError('%r takes 0 arguments' %
-                                    self.__class__.__name__)
-                raise TypeError('%r takes 0 or %d argument%s' % (
-                    self.__class__.__name__,
-                    len(self.fields),
-                    len(self.fields) != 1 and 's' or ''
-                ))
-            for name, arg in izip(self.fields, fields):
-                setattr(self, name, arg)
-        for attr in self.attributes:
-            setattr(self, attr, attributes.pop(attr, None))
-        if attributes:
-            raise TypeError('unknown attribute %r' %
-                            iter(attributes).next())
-
-    def iter_fields(self, exclude=None, only=None):
-        """This method iterates over all fields that are defined and yields
-        ``(key, value)`` tuples.  Per default all fields are returned, but
-        it's possible to limit that to some fields by providing the `only`
-        parameter or to exclude some using the `exclude` parameter.  Both
-        should be sets or tuples of field names.
-        """
-        for name in self.fields:
-            if (exclude is only is None) or \
-               (exclude is not None and name not in exclude) or \
-               (only is not None and name in only):
-                try:
-                    yield name, getattr(self, name)
-                except AttributeError:
-                    pass
-
-    def iter_child_nodes(self, exclude=None, only=None):
-        """Iterates over all direct child nodes of the node.  This iterates
-        over all fields and yields the values of they are nodes.  If the value
-        of a field is a list all the nodes in that list are returned.
-        """
-        for field, item in self.iter_fields(exclude, only):
-            if isinstance(item, list):
-                for n in item:
-                    if isinstance(n, Node):
-                        yield n
-            elif isinstance(item, Node):
-                yield item
-
-    def find(self, node_type):
-        """Find the first node of a given type.  If no such node exists the
-        return value is `None`.
-        """
-        for result in self.find_all(node_type):
-            return result
-
-    def find_all(self, node_type):
-        """Find all the nodes of a given type.  If the type is a tuple,
-        the check is performed for any of the tuple items.
-        """
-        for child in self.iter_child_nodes():
-            if isinstance(child, node_type):
-                yield child
-            for result in child.find_all(node_type):
-                yield result
-
-    def set_ctx(self, ctx):
-        """Reset the context of a node and all child nodes.  Per default the
-        parser will all generate nodes that have a 'load' context as it's the
-        most common one.  This method is used in the parser to set assignment
-        targets and other nodes to a store context.
-        """
-        todo = deque([self])
-        while todo:
-            node = todo.popleft()
-            if 'ctx' in node.fields:
-                node.ctx = ctx
-            todo.extend(node.iter_child_nodes())
-        return self
-
-    def set_lineno(self, lineno, override=False):
-        """Set the line numbers of the node and children."""
-        todo = deque([self])
-        while todo:
-            node = todo.popleft()
-            if 'lineno' in node.attributes:
-                if node.lineno is None or override:
-                    node.lineno = lineno
-            todo.extend(node.iter_child_nodes())
-        return self
-
-    def set_environment(self, environment):
-        """Set the environment for all nodes."""
-        todo = deque([self])
-        while todo:
-            node = todo.popleft()
-            node.environment = environment
-            todo.extend(node.iter_child_nodes())
-        return self
-
-    def __eq__(self, other):
-        return type(self) is type(other) and \
-               tuple(self.iter_fields()) == tuple(other.iter_fields())
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __repr__(self):
-        return '%s(%s)' % (
-            self.__class__.__name__,
-            ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
-                      arg in self.fields)
-        )
-
-
-class Stmt(Node):
-    """Base node for all statements."""
-    abstract = True
-
-
-class Helper(Node):
-    """Nodes that exist in a specific context only."""
-    abstract = True
-
-
-class Template(Node):
-    """Node that represents a template.  This must be the outermost node that
-    is passed to the compiler.
-    """
-    fields = ('body',)
-
-
-class Output(Stmt):
-    """A node that holds multiple expressions which are then printed out.
-    This is used both for the `print` statement and the regular template data.
-    """
-    fields = ('nodes',)
-
-
-class Extends(Stmt):
-    """Represents an extends statement."""
-    fields = ('template',)
-
-
-class For(Stmt):
-    """The for loop.  `target` is the target for the iteration (usually a
-    :class:`Name` or :class:`Tuple`), `iter` the iterable.  `body` is a list
-    of nodes that are used as loop-body, and `else_` a list of nodes for the
-    `else` block.  If no else node exists it has to be an empty list.
-
-    For filtered nodes an expression can be stored as `test`, otherwise `None`.
-    """
-    fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive')
-
-
-class If(Stmt):
-    """If `test` is true, `body` is rendered, else `else_`."""
-    fields = ('test', 'body', 'else_')
-
-
-class Macro(Stmt):
-    """A macro definition.  `name` is the name of the macro, `args` a list of
-    arguments and `defaults` a list of defaults if there are any.  `body` is
-    a list of nodes for the macro body.
-    """
-    fields = ('name', 'args', 'defaults', 'body')
-
-
-class CallBlock(Stmt):
-    """Like a macro without a name but a call instead.  `call` is called with
-    the unnamed macro as `caller` argument this node holds.
-    """
-    fields = ('call', 'args', 'defaults', 'body')
-
-
-class FilterBlock(Stmt):
-    """Node for filter sections."""
-    fields = ('body', 'filter')
-
-
-class Block(Stmt):
-    """A node that represents a block."""
-    fields = ('name', 'body', 'scoped')
-
-
-class Include(Stmt):
-    """A node that represents the include tag."""
-    fields = ('template', 'with_context', 'ignore_missing')
-
-
-class Import(Stmt):
-    """A node that represents the import tag."""
-    fields = ('template', 'target', 'with_context')
-
-
-class FromImport(Stmt):
-    """A node that represents the from import tag.  It's important to not
-    pass unsafe names to the name attribute.  The compiler translates the
-    attribute lookups directly into getattr calls and does *not* use the
-    subscript callback of the interface.  As exported variables may not
-    start with double underscores (which the parser asserts) this is not a
-    problem for regular Jinja code, but if this node is used in an extension
-    extra care must be taken.
-
-    The list of names may contain tuples if aliases are wanted.
-    """
-    fields = ('template', 'names', 'with_context')
-
-
-class ExprStmt(Stmt):
-    """A statement that evaluates an expression and discards the result."""
-    fields = ('node',)
-
-
-class Assign(Stmt):
-    """Assigns an expression to a target."""
-    fields = ('target', 'node')
-
-
-class Expr(Node):
-    """Baseclass for all expressions."""
-    abstract = True
-
-    def as_const(self, eval_ctx=None):
-        """Return the value of the expression as constant or raise
-        :exc:`Impossible` if this was not possible.
-
-        An :class:`EvalContext` can be provided, if none is given
-        a default context is created which requires the nodes to have
-        an attached environment.
-
-        .. versionchanged:: 2.4
-           the `eval_ctx` parameter was added.
-        """
-        raise Impossible()
-
-    def can_assign(self):
-        """Check if it's possible to assign something to this node."""
-        return False
-
-
-class BinExpr(Expr):
-    """Baseclass for all binary expressions."""
-    fields = ('left', 'right')
-    operator = None
-    abstract = True
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        f = _binop_to_func[self.operator]
-        try:
-            return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx))
-        except:
-            raise Impossible()
-
-
-class UnaryExpr(Expr):
-    """Baseclass for all unary expressions."""
-    fields = ('node',)
-    operator = None
-    abstract = True
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        f = _uaop_to_func[self.operator]
-        try:
-            return f(self.node.as_const(eval_ctx))
-        except:
-            raise Impossible()
-
-
-class Name(Expr):
-    """Looks up a name or stores a value in a name.
-    The `ctx` of the node can be one of the following values:
-
-    -   `store`: store a value in the name
-    -   `load`: load that name
-    -   `param`: like `store` but if the name was defined as function parameter.
-    """
-    fields = ('name', 'ctx')
-
-    def can_assign(self):
-        return self.name not in ('true', 'false', 'none',
-                                 'True', 'False', 'None')
-
-
-class Literal(Expr):
-    """Baseclass for literals."""
-    abstract = True
-
-
-class Const(Literal):
-    """All constant values.  The parser will return this node for simple
-    constants such as ``42`` or ``"foo"`` but it can be used to store more
-    complex values such as lists too.  Only constants with a safe
-    representation (objects where ``eval(repr(x)) == x`` is true).
-    """
-    fields = ('value',)
-
-    def as_const(self, eval_ctx=None):
-        return self.value
-
-    @classmethod
-    def from_untrusted(cls, value, lineno=None, environment=None):
-        """Return a const object if the value is representable as
-        constant value in the generated code, otherwise it will raise
-        an `Impossible` exception.
-        """
-        from compiler import has_safe_repr
-        if not has_safe_repr(value):
-            raise Impossible()
-        return cls(value, lineno=lineno, environment=environment)
-
-
-class TemplateData(Literal):
-    """A constant template string."""
-    fields = ('data',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile:
-            raise Impossible()
-        if eval_ctx.autoescape:
-            return Markup(self.data)
-        return self.data
-
-
-class Tuple(Literal):
-    """For loop unpacking and some other things like multiple arguments
-    for subscripts.  Like for :class:`Name` `ctx` specifies if the tuple
-    is used for loading the names or storing.
-    """
-    fields = ('items', 'ctx')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return tuple(x.as_const(eval_ctx) for x in self.items)
-
-    def can_assign(self):
-        for item in self.items:
-            if not item.can_assign():
-                return False
-        return True
-
-
-class List(Literal):
-    """Any list literal such as ``[1, 2, 3]``"""
-    fields = ('items',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return [x.as_const(eval_ctx) for x in self.items]
-
-
-class Dict(Literal):
-    """Any dict literal such as ``{1: 2, 3: 4}``.  The items must be a list of
-    :class:`Pair` nodes.
-    """
-    fields = ('items',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return dict(x.as_const(eval_ctx) for x in self.items)
-
-
-class Pair(Helper):
-    """A key, value pair for dicts."""
-    fields = ('key', 'value')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
-
-
-class Keyword(Helper):
-    """A key, value pair for keyword arguments where key is a string."""
-    fields = ('key', 'value')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.key, self.value.as_const(eval_ctx)
-
-
-class CondExpr(Expr):
-    """A conditional expression (inline if expression).  (``{{
-    foo if bar else baz }}``)
-    """
-    fields = ('test', 'expr1', 'expr2')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if self.test.as_const(eval_ctx):
-            return self.expr1.as_const(eval_ctx)
-
-        # if we evaluate to an undefined object, we better do that at runtime
-        if self.expr2 is None:
-            raise Impossible()
-
-        return self.expr2.as_const(eval_ctx)
-
-
-class Filter(Expr):
-    """This node applies a filter on an expression.  `name` is the name of
-    the filter, the rest of the fields are the same as for :class:`Call`.
-
-    If the `node` of a filter is `None` the contents of the last buffer are
-    filtered.  Buffers are created by macros and filter blocks.
-    """
-    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile or self.node is None:
-            raise Impossible()
-        # we have to be careful here because we call filter_ below.
-        # if this variable would be called filter, 2to3 would wrap the
-        # call in a list beause it is assuming we are talking about the
-        # builtin filter function here which no longer returns a list in
-        # python 3.  because of that, do not rename filter_ to filter!
-        filter_ = self.environment.filters.get(self.name)
-        if filter_ is None or getattr(filter_, 'contextfilter', False):
-            raise Impossible()
-        obj = self.node.as_const(eval_ctx)
-        args = [x.as_const(eval_ctx) for x in self.args]
-        if getattr(filter_, 'evalcontextfilter', False):
-            args.insert(0, eval_ctx)
-        elif getattr(filter_, 'environmentfilter', False):
-            args.insert(0, self.environment)
-        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
-        if self.dyn_args is not None:
-            try:
-                args.extend(self.dyn_args.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        if self.dyn_kwargs is not None:
-            try:
-                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        try:
-            return filter_(obj, *args, **kwargs)
-        except:
-            raise Impossible()
-
-
-class Test(Expr):
-    """Applies a test on an expression.  `name` is the name of the test, the
-    rest of the fields are the same as for :class:`Call`.
-    """
-    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
-
-
-class Call(Expr):
-    """Calls an expression.  `args` is a list of arguments, `kwargs` a list
-    of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
-    and `dyn_kwargs` has to be either `None` or a node that is used as
-    node for dynamic positional (``*args``) or keyword (``**kwargs``)
-    arguments.
-    """
-    fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile:
-            raise Impossible()
-        obj = self.node.as_const(eval_ctx)
-
-        # don't evaluate context functions
-        args = [x.as_const(eval_ctx) for x in self.args]
-        if isinstance(obj, _context_function_types):
-            if getattr(obj, 'contextfunction', False):
-                raise Impossible()
-            elif getattr(obj, 'evalcontextfunction', False):
-                args.insert(0, eval_ctx)
-            elif getattr(obj, 'environmentfunction', False):
-                args.insert(0, self.environment)
-
-        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
-        if self.dyn_args is not None:
-            try:
-                args.extend(self.dyn_args.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        if self.dyn_kwargs is not None:
-            try:
-                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        try:
-            return obj(*args, **kwargs)
-        except:
-            raise Impossible()
-
-
-class Getitem(Expr):
-    """Get an attribute or item from an expression and prefer the item."""
-    fields = ('node', 'arg', 'ctx')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if self.ctx != 'load':
-            raise Impossible()
-        try:
-            return self.environment.getitem(self.node.as_const(eval_ctx),
-                                            self.arg.as_const(eval_ctx))
-        except:
-            raise Impossible()
-
-    def can_assign(self):
-        return False
-
-
-class Getattr(Expr):
-    """Get an attribute or item from an expression that is a ascii-only
-    bytestring and prefer the attribute.
-    """
-    fields = ('node', 'attr', 'ctx')
-
-    def as_const(self, eval_ctx=None):
-        if self.ctx != 'load':
-            raise Impossible()
-        try:
-            eval_ctx = get_eval_context(self, eval_ctx)
-            return self.environment.getattr(self.node.as_const(eval_ctx),
-                                            self.attr)
-        except:
-            raise Impossible()
-
-    def can_assign(self):
-        return False
-
-
-class Slice(Expr):
-    """Represents a slice object.  This must only be used as argument for
-    :class:`Subscript`.
-    """
-    fields = ('start', 'stop', 'step')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        def const(obj):
-            if obj is None:
-                return None
-            return obj.as_const(eval_ctx)
-        return slice(const(self.start), const(self.stop), const(self.step))
-
-
-class Concat(Expr):
-    """Concatenates the list of expressions provided after converting them to
-    unicode.
-    """
-    fields = ('nodes',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes)
-
-
-class Compare(Expr):
-    """Compares an expression with some other expressions.  `ops` must be a
-    list of :class:`Operand`\s.
-    """
-    fields = ('expr', 'ops')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        result = value = self.expr.as_const(eval_ctx)
-        try:
-            for op in self.ops:
-                new_value = op.expr.as_const(eval_ctx)
-                result = _cmpop_to_func[op.op](value, new_value)
-                value = new_value
-        except:
-            raise Impossible()
-        return result
-
-
-class Operand(Helper):
-    """Holds an operator and an expression."""
-    fields = ('op', 'expr')
-
-if __debug__:
-    Operand.__doc__ += '\nThe following operators are available: ' + \
-        ', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
-                  set(_uaop_to_func) | set(_cmpop_to_func)))
-
-
-class Mul(BinExpr):
-    """Multiplies the left with the right node."""
-    operator = '*'
-
-
-class Div(BinExpr):
-    """Divides the left by the right node."""
-    operator = '/'
-
-
-class FloorDiv(BinExpr):
-    """Divides the left by the right node and truncates conver the
-    result into an integer by truncating.
-    """
-    operator = '//'
-
-
-class Add(BinExpr):
-    """Add the left to the right node."""
-    operator = '+'
-
-
-class Sub(BinExpr):
-    """Substract the right from the left node."""
-    operator = '-'
-
-
-class Mod(BinExpr):
-    """Left modulo right."""
-    operator = '%'
-
-
-class Pow(BinExpr):
-    """Left to the power of right."""
-    operator = '**'
-
-
-class And(BinExpr):
-    """Short circuited AND."""
-    operator = 'and'
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx)
-
-
-class Or(BinExpr):
-    """Short circuited OR."""
-    operator = 'or'
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx)
-
-
-class Not(UnaryExpr):
-    """Negate the expression."""
-    operator = 'not'
-
-
-class Neg(UnaryExpr):
-    """Make the expression negative."""
-    operator = '-'
-
-
-class Pos(UnaryExpr):
-    """Make the expression positive (noop for most expressions)"""
-    operator = '+'
-
-
-# Helpers for extensions
-
-
-class EnvironmentAttribute(Expr):
-    """Loads an attribute from the environment object.  This is useful for
-    extensions that want to call a callback stored on the environment.
-    """
-    fields = ('name',)
-
-
-class ExtensionAttribute(Expr):
-    """Returns the attribute of an extension bound to the environment.
-    The identifier is the identifier of the :class:`Extension`.
-
-    This node is usually constructed by calling the
-    :meth:`~ambari_jinja2.ext.Extension.attr` method on an extension.
-    """
-    fields = ('identifier', 'name')
-
-
-class ImportedName(Expr):
-    """If created with an import name the import name is returned on node
-    access.  For example ``ImportedName('cgi.escape')`` returns the `escape`
-    function from the cgi module on evaluation.  Imports are optimized by the
-    compiler so there is no need to assign them to local variables.
-    """
-    fields = ('importname',)
-
-
-class InternalName(Expr):
-    """An internal name in the compiler.  You cannot create these nodes
-    yourself but the parser provides a
-    :meth:`~ambari_jinja2.parser.Parser.free_identifier` method that creates
-    a new identifier for you.  This identifier is not available from the
-    template and is not threated specially by the compiler.
-    """
-    fields = ('name',)
-
-    def __init__(self):
-        raise TypeError('Can\'t create internal names.  Use the '
-                        '`free_identifier` method on a parser.')
-
-
-class MarkSafe(Expr):
-    """Mark the wrapped expression as safe (wrap it as `Markup`)."""
-    fields = ('expr',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return Markup(self.expr.as_const(eval_ctx))
-
-
-class MarkSafeIfAutoescape(Expr):
-    """Mark the wrapped expression as safe (wrap it as `Markup`) but
-    only if autoescaping is active.
-
-    .. versionadded:: 2.5
-    """
-    fields = ('expr',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile:
-            raise Impossible()
-        expr = self.expr.as_const(eval_ctx)
-        if eval_ctx.autoescape:
-            return Markup(expr)
-        return expr
-
-
-class ContextReference(Expr):
-    """Returns the current template context.  It can be used like a
-    :class:`Name` node, with a ``'load'`` ctx and will return the
-    current :class:`~ambari_jinja2.runtime.Context` object.
-
-    Here an example that assigns the current template name to a
-    variable named `foo`::
-
-        Assign(Name('foo', ctx='store'),
-               Getattr(ContextReference(), 'name'))
-    """
-
-
-class Continue(Stmt):
-    """Continue a loop."""
-
-
-class Break(Stmt):
-    """Break a loop."""
-
-
-class Scope(Stmt):
-    """An artificial scope."""
-    fields = ('body',)
-
-
-class EvalContextModifier(Stmt):
-    """Modifies the eval context.  For each option that should be modified,
-    a :class:`Keyword` has to be added to the :attr:`options` list.
-
-    Example to change the `autoescape` setting::
-
-        EvalContextModifier(options=[Keyword('autoescape', Const(True))])
-    """
-    fields = ('options',)
-
-
-class ScopedEvalContextModifier(EvalContextModifier):
-    """Modifies the eval context and reverts it later.  Works exactly like
-    :class:`EvalContextModifier` but will only modify the
-    :class:`~ambari_jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
-    """
-    fields = ('body',)
-
-
-# make sure nobody creates custom nodes
-def _failing_new(*args, **kwargs):
-    raise TypeError('can\'t create custom node types')
-NodeType.__new__ = staticmethod(_failing_new); del _failing_new

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py
deleted file mode 100644
index b014396..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.optimizer
-    ~~~~~~~~~~~~~~~~
-
-    The jinja optimizer is currently trying to constant fold a few expressions
-    and modify the AST in place so that it should be easier to evaluate it.
-
-    Because the AST does not contain all the scoping information and the
-    compiler has to find that out, we cannot do all the optimizations we
-    want.  For example loop unrolling doesn't work because unrolled loops would
-    have a different scoping.
-
-    The solution would be a second syntax tree that has the scoping rules stored.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from ambari_jinja2 import nodes
-from ambari_jinja2.visitor import NodeTransformer
-
-
-def optimize(node, environment):
-    """The context hint can be used to perform an static optimization
-    based on the context given."""
-    optimizer = Optimizer(environment)
-    return optimizer.visit(node)
-
-
-class Optimizer(NodeTransformer):
-
-    def __init__(self, environment):
-        self.environment = environment
-
-    def visit_If(self, node):
-        """Eliminate dead code."""
-        # do not optimize ifs that have a block inside so that it doesn't
-        # break super().
-        if node.find(nodes.Block) is not None:
-            return self.generic_visit(node)
-        try:
-            val = self.visit(node.test).as_const()
-        except nodes.Impossible:
-            return self.generic_visit(node)
-        if val:
-            body = node.body
-        else:
-            body = node.else_
-        result = []
-        for node in body:
-            result.extend(self.visit_list(node))
-        return result
-
-    def fold(self, node):
-        """Do constant folding."""
-        node = self.generic_visit(node)
-        try:
-            return nodes.Const.from_untrusted(node.as_const(),
-                                              lineno=node.lineno,
-                                              environment=self.environment)
-        except nodes.Impossible:
-            return node
-
-    visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
-    visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
-    visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \
-    visit_Filter = visit_Test = visit_CondExpr = fold
-    del fold

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py
deleted file mode 100644
index a14c055..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py
+++ /dev/null
@@ -1,896 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.parser
-    ~~~~~~~~~~~~~
-
-    Implements the template parser.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from ambari_jinja2 import nodes
-from ambari_jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
-from ambari_jinja2.utils import next
-from ambari_jinja2.lexer import describe_token, describe_token_expr
-
-
-#: statements that callinto 
-_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
-                                 'macro', 'include', 'from', 'import',
-                                 'set'])
-_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
-
-
-class Parser(object):
-    """This is the central parsing class Jinja2 uses.  It's passed to
-    extensions and can be used to parse expressions or statements.
-    """
-
-    def __init__(self, environment, source, name=None, filename=None,
-                 state=None):
-        self.environment = environment
-        self.stream = environment._tokenize(source, name, filename, state)
-        self.name = name
-        self.filename = filename
-        self.closed = False
-        self.extensions = {}
-        for extension in environment.iter_extensions():
-            for tag in extension.tags:
-                self.extensions[tag] = extension.parse
-        self._last_identifier = 0
-        self._tag_stack = []
-        self._end_token_stack = []
-
-    def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
-        """Convenience method that raises `exc` with the message, passed
-        line number or last line number as well as the current name and
-        filename.
-        """
-        if lineno is None:
-            lineno = self.stream.current.lineno
-        raise exc(msg, lineno, self.name, self.filename)
-
-    def _fail_ut_eof(self, name, end_token_stack, lineno):
-        expected = []
-        for exprs in end_token_stack:
-            expected.extend(map(describe_token_expr, exprs))
-        if end_token_stack:
-            currently_looking = ' or '.join(
-                "'%s'" % describe_token_expr(expr)
-                for expr in end_token_stack[-1])
-        else:
-            currently_looking = None
-
-        if name is None:
-            message = ['Unexpected end of template.']
-        else:
-            message = ['Encountered unknown tag \'%s\'.' % name]
-
-        if currently_looking:
-            if name is not None and name in expected:
-                message.append('You probably made a nesting mistake. Jinja '
-                               'is expecting this tag, but currently looking '
-                               'for %s.' % currently_looking)
-            else:
-                message.append('Jinja was looking for the following tags: '
-                               '%s.' % currently_looking)
-
-        if self._tag_stack:
-            message.append('The innermost block that needs to be '
-                           'closed is \'%s\'.' % self._tag_stack[-1])
-
-        self.fail(' '.join(message), lineno)
-
-    def fail_unknown_tag(self, name, lineno=None):
-        """Called if the parser encounters an unknown tag.  Tries to fail
-        with a human readable error message that could help to identify
-        the problem.
-        """
-        return self._fail_ut_eof(name, self._end_token_stack, lineno)
-
-    def fail_eof(self, end_tokens=None, lineno=None):
-        """Like fail_unknown_tag but for end of template situations."""
-        stack = list(self._end_token_stack)
-        if end_tokens is not None:
-            stack.append(end_tokens)
-        return self._fail_ut_eof(None, stack, lineno)
-
-    def is_tuple_end(self, extra_end_rules=None):
-        """Are we at the end of a tuple?"""
-        if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
-            return True
-        elif extra_end_rules is not None:
-            return self.stream.current.test_any(extra_end_rules)
-        return False
-
-    def free_identifier(self, lineno=None):
-        """Return a new free identifier as :class:`~ambari_jinja2.nodes.InternalName`."""
-        self._last_identifier += 1
-        rv = object.__new__(nodes.InternalName)
-        nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
-        return rv
-
-    def parse_statement(self):
-        """Parse a single statement."""
-        token = self.stream.current
-        if token.type != 'name':
-            self.fail('tag name expected', token.lineno)
-        self._tag_stack.append(token.value)
-        pop_tag = True
-        try:
-            if token.value in _statement_keywords:
-                return getattr(self, 'parse_' + self.stream.current.value)()
-            if token.value == 'call':
-                return self.parse_call_block()
-            if token.value == 'filter':
-                return self.parse_filter_block()
-            ext = self.extensions.get(token.value)
-            if ext is not None:
-                return ext(self)
-
-            # did not work out, remove the token we pushed by accident
-            # from the stack so that the unknown tag fail function can
-            # produce a proper error message.
-            self._tag_stack.pop()
-            pop_tag = False
-            self.fail_unknown_tag(token.value, token.lineno)
-        finally:
-            if pop_tag:
-                self._tag_stack.pop()
-
-    def parse_statements(self, end_tokens, drop_needle=False):
-        """Parse multiple statements into a list until one of the end tokens
-        is reached.  This is used to parse the body of statements as it also
-        parses template data if appropriate.  The parser checks first if the
-        current token is a colon and skips it if there is one.  Then it checks
-        for the block end and parses until if one of the `end_tokens` is
-        reached.  Per default the active token in the stream at the end of
-        the call is the matched end token.  If this is not wanted `drop_needle`
-        can be set to `True` and the end token is removed.
-        """
-        # the first token may be a colon for python compatibility
-        self.stream.skip_if('colon')
-
-        # in the future it would be possible to add whole code sections
-        # by adding some sort of end of statement token and parsing those here.
-        self.stream.expect('block_end')
-        result = self.subparse(end_tokens)
-
-        # we reached the end of the template too early, the subparser
-        # does not check for this, so we do that now
-        if self.stream.current.type == 'eof':
-            self.fail_eof(end_tokens)
-
-        if drop_needle:
-            next(self.stream)
-        return result
-
-    def parse_set(self):
-        """Parse an assign statement."""
-        lineno = next(self.stream).lineno
-        target = self.parse_assign_target()
-        self.stream.expect('assign')
-        expr = self.parse_tuple()
-        return nodes.Assign(target, expr, lineno=lineno)
-
-    def parse_for(self):
-        """Parse a for loop."""
-        lineno = self.stream.expect('name:for').lineno
-        target = self.parse_assign_target(extra_end_rules=('name:in',))
-        self.stream.expect('name:in')
-        iter = self.parse_tuple(with_condexpr=False,
-                                extra_end_rules=('name:recursive',))
-        test = None
-        if self.stream.skip_if('name:if'):
-            test = self.parse_expression()
-        recursive = self.stream.skip_if('name:recursive')
-        body = self.parse_statements(('name:endfor', 'name:else'))
-        if next(self.stream).value == 'endfor':
-            else_ = []
-        else:
-            else_ = self.parse_statements(('name:endfor',), drop_needle=True)
-        return nodes.For(target, iter, body, else_, test,
-                         recursive, lineno=lineno)
-
-    def parse_if(self):
-        """Parse an if construct."""
-        node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
-        while 1:
-            node.test = self.parse_tuple(with_condexpr=False)
-            node.body = self.parse_statements(('name:elif', 'name:else',
-                                               'name:endif'))
-            token = next(self.stream)
-            if token.test('name:elif'):
-                new_node = nodes.If(lineno=self.stream.current.lineno)
-                node.else_ = [new_node]
-                node = new_node
-                continue
-            elif token.test('name:else'):
-                node.else_ = self.parse_statements(('name:endif',),
-                                                   drop_needle=True)
-            else:
-                node.else_ = []
-            break
-        return result
-
-    def parse_block(self):
-        node = nodes.Block(lineno=next(self.stream).lineno)
-        node.name = self.stream.expect('name').value
-        node.scoped = self.stream.skip_if('name:scoped')
-
-        # common problem people encounter when switching from django
-        # to jinja.  we do not support hyphens in block names, so let's
-        # raise a nicer error message in that case.
-        if self.stream.current.type == 'sub':
-            self.fail('Block names in Jinja have to be valid Python '
-                      'identifiers and may not contain hypens, use an '
-                      'underscore instead.')
-
-        node.body = self.parse_statements(('name:endblock',), drop_needle=True)
-        self.stream.skip_if('name:' + node.name)
-        return node
-
-    def parse_extends(self):
-        node = nodes.Extends(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        return node
-
-    def parse_import_context(self, node, default):
-        if self.stream.current.test_any('name:with', 'name:without') and \
-           self.stream.look().test('name:context'):
-            node.with_context = next(self.stream).value == 'with'
-            self.stream.skip()
-        else:
-            node.with_context = default
-        return node
-
-    def parse_include(self):
-        node = nodes.Include(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        if self.stream.current.test('name:ignore') and \
-           self.stream.look().test('name:missing'):
-            node.ignore_missing = True
-            self.stream.skip(2)
-        else:
-            node.ignore_missing = False
-        return self.parse_import_context(node, True)
-
-    def parse_import(self):
-        node = nodes.Import(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        self.stream.expect('name:as')
-        node.target = self.parse_assign_target(name_only=True).name
-        return self.parse_import_context(node, False)
-
-    def parse_from(self):
-        node = nodes.FromImport(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        self.stream.expect('name:import')
-        node.names = []
-
-        def parse_context():
-            if self.stream.current.value in ('with', 'without') and \
-               self.stream.look().test('name:context'):
-                node.with_context = next(self.stream).value == 'with'
-                self.stream.skip()
-                return True
-            return False
-
-        while 1:
-            if node.names:
-                self.stream.expect('comma')
-            if self.stream.current.type == 'name':
-                if parse_context():
-                    break
-                target = self.parse_assign_target(name_only=True)
-                if target.name.startswith('_'):
-                    self.fail('names starting with an underline can not '
-                              'be imported', target.lineno,
-                              exc=TemplateAssertionError)
-                if self.stream.skip_if('name:as'):
-                    alias = self.parse_assign_target(name_only=True)
-                    node.names.append((target.name, alias.name))
-                else:
-                    node.names.append(target.name)
-                if parse_context() or self.stream.current.type != 'comma':
-                    break
-            else:
-                break
-        if not hasattr(node, 'with_context'):
-            node.with_context = False
-            self.stream.skip_if('comma')
-        return node
-
-    def parse_signature(self, node):
-        node.args = args = []
-        node.defaults = defaults = []
-        self.stream.expect('lparen')
-        while self.stream.current.type != 'rparen':
-            if args:
-                self.stream.expect('comma')
-            arg = self.parse_assign_target(name_only=True)
-            arg.set_ctx('param')
-            if self.stream.skip_if('assign'):
-                defaults.append(self.parse_expression())
-            args.append(arg)
-        self.stream.expect('rparen')
-
-    def parse_call_block(self):
-        node = nodes.CallBlock(lineno=next(self.stream).lineno)
-        if self.stream.current.type == 'lparen':
-            self.parse_signature(node)
-        else:
-            node.args = []
-            node.defaults = []
-
-        node.call = self.parse_expression()
-        if not isinstance(node.call, nodes.Call):
-            self.fail('expected call', node.lineno)
-        node.body = self.parse_statements(('name:endcall',), drop_needle=True)
-        return node
-
-    def parse_filter_block(self):
-        node = nodes.FilterBlock(lineno=next(self.stream).lineno)
-        node.filter = self.parse_filter(None, start_inline=True)
-        node.body = self.parse_statements(('name:endfilter',),
-                                          drop_needle=True)
-        return node
-
-    def parse_macro(self):
-        node = nodes.Macro(lineno=next(self.stream).lineno)
-        node.name = self.parse_assign_target(name_only=True).name
-        self.parse_signature(node)
-        node.body = self.parse_statements(('name:endmacro',),
-                                          drop_needle=True)
-        return node
-
-    def parse_print(self):
-        node = nodes.Output(lineno=next(self.stream).lineno)
-        node.nodes = []
-        while self.stream.current.type != 'block_end':
-            if node.nodes:
-                self.stream.expect('comma')
-            node.nodes.append(self.parse_expression())
-        return node
-
-    def parse_assign_target(self, with_tuple=True, name_only=False,
-                            extra_end_rules=None):
-        """Parse an assignment target.  As Jinja2 allows assignments to
-        tuples, this function can parse all allowed assignment targets.  Per
-        default assignments to tuples are parsed, that can be disable however
-        by setting `with_tuple` to `False`.  If only assignments to names are
-        wanted `name_only` can be set to `True`.  The `extra_end_rules`
-        parameter is forwarded to the tuple parsing function.
-        """
-        if name_only:
-            token = self.stream.expect('name')
-            target = nodes.Name(token.value, 'store', lineno=token.lineno)
-        else:
-            if with_tuple:
-                target = self.parse_tuple(simplified=True,
-                                          extra_end_rules=extra_end_rules)
-            else:
-                target = self.parse_primary()
-            target.set_ctx('store')
-        if not target.can_assign():
-            self.fail('can\'t assign to %r' % target.__class__.
-                      __name__.lower(), target.lineno)
-        return target
-
-    def parse_expression(self, with_condexpr=True):
-        """Parse an expression.  Per default all expressions are parsed, if
-        the optional `with_condexpr` parameter is set to `False` conditional
-        expressions are not parsed.
-        """
-        if with_condexpr:
-            return self.parse_condexpr()
-        return self.parse_or()
-
-    def parse_condexpr(self):
-        lineno = self.stream.current.lineno
-        expr1 = self.parse_or()
-        while self.stream.skip_if('name:if'):
-            expr2 = self.parse_or()
-            if self.stream.skip_if('name:else'):
-                expr3 = self.parse_condexpr()
-            else:
-                expr3 = None
-            expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return expr1
-
-    def parse_or(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_and()
-        while self.stream.skip_if('name:or'):
-            right = self.parse_and()
-            left = nodes.Or(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_and(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_not()
-        while self.stream.skip_if('name:and'):
-            right = self.parse_not()
-            left = nodes.And(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_not(self):
-        if self.stream.current.test('name:not'):
-            lineno = next(self.stream).lineno
-            return nodes.Not(self.parse_not(), lineno=lineno)
-        return self.parse_compare()
-
-    def parse_compare(self):
-        lineno = self.stream.current.lineno
-        expr = self.parse_add()
-        ops = []
-        while 1:
-            token_type = self.stream.current.type
-            if token_type in _compare_operators:
-                next(self.stream)
-                ops.append(nodes.Operand(token_type, self.parse_add()))
-            elif self.stream.skip_if('name:in'):
-                ops.append(nodes.Operand('in', self.parse_add()))
-            elif self.stream.current.test('name:not') and \
-                 self.stream.look().test('name:in'):
-                self.stream.skip(2)
-                ops.append(nodes.Operand('notin', self.parse_add()))
-            else:
-                break
-            lineno = self.stream.current.lineno
-        if not ops:
-            return expr
-        return nodes.Compare(expr, ops, lineno=lineno)
-
-    def parse_add(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_sub()
-        while self.stream.current.type == 'add':
-            next(self.stream)
-            right = self.parse_sub()
-            left = nodes.Add(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_sub(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_concat()
-        while self.stream.current.type == 'sub':
-            next(self.stream)
-            right = self.parse_concat()
-            left = nodes.Sub(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_concat(self):
-        lineno = self.stream.current.lineno
-        args = [self.parse_mul()]
-        while self.stream.current.type == 'tilde':
-            next(self.stream)
-            args.append(self.parse_mul())
-        if len(args) == 1:
-            return args[0]
-        return nodes.Concat(args, lineno=lineno)
-
-    def parse_mul(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_div()
-        while self.stream.current.type == 'mul':
-            next(self.stream)
-            right = self.parse_div()
-            left = nodes.Mul(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_div(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_floordiv()
-        while self.stream.current.type == 'div':
-            next(self.stream)
-            right = self.parse_floordiv()
-            left = nodes.Div(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_floordiv(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_mod()
-        while self.stream.current.type == 'floordiv':
-            next(self.stream)
-            right = self.parse_mod()
-            left = nodes.FloorDiv(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_mod(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_pow()
-        while self.stream.current.type == 'mod':
-            next(self.stream)
-            right = self.parse_pow()
-            left = nodes.Mod(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_pow(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_unary()
-        while self.stream.current.type == 'pow':
-            next(self.stream)
-            right = self.parse_unary()
-            left = nodes.Pow(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_unary(self, with_filter=True):
-        token_type = self.stream.current.type
-        lineno = self.stream.current.lineno
-        if token_type == 'sub':
-            next(self.stream)
-            node = nodes.Neg(self.parse_unary(False), lineno=lineno)
-        elif token_type == 'add':
-            next(self.stream)
-            node = nodes.Pos(self.parse_unary(False), lineno=lineno)
-        else:
-            node = self.parse_primary()
-        node = self.parse_postfix(node)
-        if with_filter:
-            node = self.parse_filter_expr(node)
-        return node
-
-    def parse_primary(self):
-        token = self.stream.current
-        if token.type == 'name':
-            if token.value in ('true', 'false', 'True', 'False'):
-                node = nodes.Const(token.value in ('true', 'True'),
-                                   lineno=token.lineno)
-            elif token.value in ('none', 'None'):
-                node = nodes.Const(None, lineno=token.lineno)
-            else:
-                node = nodes.Name(token.value, 'load', lineno=token.lineno)
-            next(self.stream)
-        elif token.type == 'string':
-            next(self.stream)
-            buf = [token.value]
-            lineno = token.lineno
-            while self.stream.current.type == 'string':
-                buf.append(self.stream.current.value)
-                next(self.stream)
-            node = nodes.Const(''.join(buf), lineno=lineno)
-        elif token.type in ('integer', 'float'):
-            next(self.stream)
-            node = nodes.Const(token.value, lineno=token.lineno)
-        elif token.type == 'lparen':
-            next(self.stream)
-            node = self.parse_tuple(explicit_parentheses=True)
-            self.stream.expect('rparen')
-        elif token.type == 'lbracket':
-            node = self.parse_list()
-        elif token.type == 'lbrace':
-            node = self.parse_dict()
-        else:
-            self.fail("unexpected '%s'" % describe_token(token), token.lineno)
-        return node
-
-    def parse_tuple(self, simplified=False, with_condexpr=True,
-                    extra_end_rules=None, explicit_parentheses=False):
-        """Works like `parse_expression` but if multiple expressions are
-        delimited by a comma a :class:`~ambari_jinja2.nodes.Tuple` node is created.
-        This method could also return a regular expression instead of a tuple
-        if no commas where found.
-
-        The default parsing mode is a full tuple.  If `simplified` is `True`
-        only names and literals are parsed.  The `no_condexpr` parameter is
-        forwarded to :meth:`parse_expression`.
-
-        Because tuples do not require delimiters and may end in a bogus comma
-        an extra hint is needed that marks the end of a tuple.  For example
-        for loops support tuples between `for` and `in`.  In that case the
-        `extra_end_rules` is set to ``['name:in']``.
-
-        `explicit_parentheses` is true if the parsing was triggered by an
-        expression in parentheses.  This is used to figure out if an empty
-        tuple is a valid expression or not.
-        """
-        lineno = self.stream.current.lineno
-        if simplified:
-            parse = self.parse_primary
-        elif with_condexpr:
-            parse = self.parse_expression
-        else:
-            parse = lambda: self.parse_expression(with_condexpr=False)
-        args = []
-        is_tuple = False
-        while 1:
-            if args:
-                self.stream.expect('comma')
-            if self.is_tuple_end(extra_end_rules):
-                break
-            args.append(parse())
-            if self.stream.current.type == 'comma':
-                is_tuple = True
-            else:
-                break
-            lineno = self.stream.current.lineno
-
-        if not is_tuple:
-            if args:
-                return args[0]
-
-            # if we don't have explicit parentheses, an empty tuple is
-            # not a valid expression.  This would mean nothing (literally
-            # nothing) in the spot of an expression would be an empty
-            # tuple.
-            if not explicit_parentheses:
-                self.fail('Expected an expression, got \'%s\'' %
-                          describe_token(self.stream.current))
-
-        return nodes.Tuple(args, 'load', lineno=lineno)
-
-    def parse_list(self):
-        token = self.stream.expect('lbracket')
-        items = []
-        while self.stream.current.type != 'rbracket':
-            if items:
-                self.stream.expect('comma')
-            if self.stream.current.type == 'rbracket':
-                break
-            items.append(self.parse_expression())
-        self.stream.expect('rbracket')
-        return nodes.List(items, lineno=token.lineno)
-
-    def parse_dict(self):
-        token = self.stream.expect('lbrace')
-        items = []
-        while self.stream.current.type != 'rbrace':
-            if items:
-                self.stream.expect('comma')
-            if self.stream.current.type == 'rbrace':
-                break
-            key = self.parse_expression()
-            self.stream.expect('colon')
-            value = self.parse_expression()
-            items.append(nodes.Pair(key, value, lineno=key.lineno))
-        self.stream.expect('rbrace')
-        return nodes.Dict(items, lineno=token.lineno)
-
-    def parse_postfix(self, node):
-        while 1:
-            token_type = self.stream.current.type
-            if token_type == 'dot' or token_type == 'lbracket':
-                node = self.parse_subscript(node)
-            # calls are valid both after postfix expressions (getattr
-            # and getitem) as well as filters and tests
-            elif token_type == 'lparen':
-                node = self.parse_call(node)
-            else:
-                break
-        return node
-
-    def parse_filter_expr(self, node):
-        while 1:
-            token_type = self.stream.current.type
-            if token_type == 'pipe':
-                node = self.parse_filter(node)
-            elif token_type == 'name' and self.stream.current.value == 'is':
-                node = self.parse_test(node)
-            # calls are valid both after postfix expressions (getattr
-            # and getitem) as well as filters and tests
-            elif token_type == 'lparen':
-                node = self.parse_call(node)
-            else:
-                break
-        return node
-
-    def parse_subscript(self, node):
-        token = next(self.stream)
-        if token.type == 'dot':
-            attr_token = self.stream.current
-            next(self.stream)
-            if attr_token.type == 'name':
-                return nodes.Getattr(node, attr_token.value, 'load',
-                                     lineno=token.lineno)
-            elif attr_token.type != 'integer':
-                self.fail('expected name or number', attr_token.lineno)
-            arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
-            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
-        if token.type == 'lbracket':
-            priority_on_attribute = False
-            args = []
-            while self.stream.current.type != 'rbracket':
-                if args:
-                    self.stream.expect('comma')
-                args.append(self.parse_subscribed())
-            self.stream.expect('rbracket')
-            if len(args) == 1:
-                arg = args[0]
-            else:
-                arg = nodes.Tuple(args, 'load', lineno=token.lineno)
-            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
-        self.fail('expected subscript expression', self.lineno)
-
-    def parse_subscribed(self):
-        lineno = self.stream.current.lineno
-
-        if self.stream.current.type == 'colon':
-            next(self.stream)
-            args = [None]
-        else:
-            node = self.parse_expression()
-            if self.stream.current.type != 'colon':
-                return node
-            next(self.stream)
-            args = [node]
-
-        if self.stream.current.type == 'colon':
-            args.append(None)
-        elif self.stream.current.type not in ('rbracket', 'comma'):
-            args.append(self.parse_expression())
-        else:
-            args.append(None)
-
-        if self.stream.current.type == 'colon':
-            next(self.stream)
-            if self.stream.current.type not in ('rbracket', 'comma'):
-                args.append(self.parse_expression())
-            else:
-                args.append(None)
-        else:
-            args.append(None)
-
-        return nodes.Slice(lineno=lineno, *args)
-
-    def parse_call(self, node):
-        token = self.stream.expect('lparen')
-        args = []
-        kwargs = []
-        dyn_args = dyn_kwargs = None
-        require_comma = False
-
-        def ensure(expr):
-            if not expr:
-                self.fail('invalid syntax for function call expression',
-                          token.lineno)
-
-        while self.stream.current.type != 'rparen':
-            if require_comma:
-                self.stream.expect('comma')
-                # support for trailing comma
-                if self.stream.current.type == 'rparen':
-                    break
-            if self.stream.current.type == 'mul':
-                ensure(dyn_args is None and dyn_kwargs is None)
-                next(self.stream)
-                dyn_args = self.parse_expression()
-            elif self.stream.current.type == 'pow':
-                ensure(dyn_kwargs is None)
-                next(self.stream)
-                dyn_kwargs = self.parse_expression()
-            else:
-                ensure(dyn_args is None and dyn_kwargs is None)
-                if self.stream.current.type == 'name' and \
-                    self.stream.look().type == 'assign':
-                    key = self.stream.current.value
-                    self.stream.skip(2)
-                    value = self.parse_expression()
-                    kwargs.append(nodes.Keyword(key, value,
-                                                lineno=value.lineno))
-                else:
-                    ensure(not kwargs)
-                    args.append(self.parse_expression())
-
-            require_comma = True
-        self.stream.expect('rparen')
-
-        if node is None:
-            return args, kwargs, dyn_args, dyn_kwargs
-        return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
-                          lineno=token.lineno)
-
-    def parse_filter(self, node, start_inline=False):
-        while self.stream.current.type == 'pipe' or start_inline:
-            if not start_inline:
-                next(self.stream)
-            token = self.stream.expect('name')
-            name = token.value
-            while self.stream.current.type == 'dot':
-                next(self.stream)
-                name += '.' + self.stream.expect('name').value
-            if self.stream.current.type == 'lparen':
-                args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
-            else:
-                args = []
-                kwargs = []
-                dyn_args = dyn_kwargs = None
-            node = nodes.Filter(node, name, args, kwargs, dyn_args,
-                                dyn_kwargs, lineno=token.lineno)
-            start_inline = False
-        return node
-
-    def parse_test(self, node):
-        token = next(self.stream)
-        if self.stream.current.test('name:not'):
-            next(self.stream)
-            negated = True
-        else:
-            negated = False
-        name = self.stream.expect('name').value
-        while self.stream.current.type == 'dot':
-            next(self.stream)
-            name += '.' + self.stream.expect('name').value
-        dyn_args = dyn_kwargs = None
-        kwargs = []
-        if self.stream.current.type == 'lparen':
-            args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
-        elif self.stream.current.type in ('name', 'string', 'integer',
-                                          'float', 'lparen', 'lbracket',
-                                          'lbrace') and not \
-             self.stream.current.test_any('name:else', 'name:or',
-                                          'name:and'):
-            if self.stream.current.test('name:is'):
-                self.fail('You cannot chain multiple tests with is')
-            args = [self.parse_expression()]
-        else:
-            args = []
-        node = nodes.Test(node, name, args, kwargs, dyn_args,
-                          dyn_kwargs, lineno=token.lineno)
-        if negated:
-            node = nodes.Not(node, lineno=token.lineno)
-        return node
-
-    def subparse(self, end_tokens=None):
-        body = []
-        data_buffer = []
-        add_data = data_buffer.append
-
-        if end_tokens is not None:
-            self._end_token_stack.append(end_tokens)
-
-        def flush_data():
-            if data_buffer:
-                lineno = data_buffer[0].lineno
-                body.append(nodes.Output(data_buffer[:], lineno=lineno))
-                del data_buffer[:]
-
-        try:
-            while self.stream:
-                token = self.stream.current
-                if token.type == 'data':
-                    if token.value:
-                        add_data(nodes.TemplateData(token.value,
-                                                    lineno=token.lineno))
-                    next(self.stream)
-                elif token.type == 'variable_begin':
-                    next(self.stream)
-                    add_data(self.parse_tuple(with_condexpr=True))
-                    self.stream.expect('variable_end')
-                elif token.type == 'block_begin':
-                    flush_data()
-                    next(self.stream)
-                    if end_tokens is not None and \
-                       self.stream.current.test_any(*end_tokens):
-                        return body
-                    rv = self.parse_statement()
-                    if isinstance(rv, list):
-                        body.extend(rv)
-                    else:
-                        body.append(rv)
-                    self.stream.expect('block_end')
-                else:
-                    raise AssertionError('internal parsing error')
-
-            flush_data()
-        finally:
-            if end_tokens is not None:
-                self._end_token_stack.pop()
-
-        return body
-
-    def parse(self):
-        """Parse the whole template into a `Template` node."""
-        result = nodes.Template(self.subparse(), lineno=1)
-        result.set_environment(self.environment)
-        return result

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py
deleted file mode 100644
index 0830132..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py
+++ /dev/null
@@ -1,544 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.runtime
-    ~~~~~~~~~~~~~~
-
-    Runtime helpers.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-import sys
-from itertools import chain, imap
-from ambari_jinja2.nodes import EvalContext, _context_function_types
-from ambari_jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
-     concat, internalcode, next, object_type_repr
-from ambari_jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
-     TemplateNotFound
-
-
-# these variables are exported to the template runtime
-__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
-           'TemplateRuntimeError', 'missing', 'concat', 'escape',
-           'markup_join', 'unicode_join', 'to_string', 'identity',
-           'TemplateNotFound']
-
-#: the name of the function that is used to convert something into
-#: a string.  2to3 will adopt that automatically and the generated
-#: code can take advantage of it.
-to_string = unicode
-
-#: the identity function.  Useful for certain things in the environment
-identity = lambda x: x
-
-
-def markup_join(seq):
-    """Concatenation that escapes if necessary and converts to unicode."""
-    buf = []
-    iterator = imap(soft_unicode, seq)
-    for arg in iterator:
-        buf.append(arg)
-        if hasattr(arg, '__html__'):
-            return Markup(u'').join(chain(buf, iterator))
-    return concat(buf)
-
-
-def unicode_join(seq):
-    """Simple args to unicode conversion and concatenation."""
-    return concat(imap(unicode, seq))
-
-
-def new_context(environment, template_name, blocks, vars=None,
-                shared=None, globals=None, locals=None):
-    """Internal helper to for context creation."""
-    if vars is None:
-        vars = {}
-    if shared:
-        parent = vars
-    else:
-        parent = dict(globals or (), **vars)
-    if locals:
-        # if the parent is shared a copy should be created because
-        # we don't want to modify the dict passed
-        if shared:
-            parent = dict(parent)
-        for key, value in locals.iteritems():
-            if key[:2] == 'l_' and value is not missing:
-                parent[key[2:]] = value
-    return Context(environment, parent, template_name, blocks)
-
-
-class TemplateReference(object):
-    """The `self` in templates."""
-
-    def __init__(self, context):
-        self.__context = context
-
-    def __getitem__(self, name):
-        blocks = self.__context.blocks[name]
-        wrap = self.__context.eval_ctx.autoescape and \
-               Markup or (lambda x: x)
-        return BlockReference(name, self.__context, blocks, 0)
-
-    def __repr__(self):
-        return '<%s %r>' % (
-            self.__class__.__name__,
-            self.__context.name
-        )
-
-
-class Context(object):
-    """The template context holds the variables of a template.  It stores the
-    values passed to the template and also the names the template exports.
-    Creating instances is neither supported nor useful as it's created
-    automatically at various stages of the template evaluation and should not
-    be created by hand.
-
-    The context is immutable.  Modifications on :attr:`parent` **must not**
-    happen and modifications on :attr:`vars` are allowed from generated
-    template code only.  Template filters and global functions marked as
-    :func:`contextfunction`\s get the active context passed as first argument
-    and are allowed to access the context read-only.
-
-    The template context supports read only dict operations (`get`,
-    `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
-    `__getitem__`, `__contains__`).  Additionally there is a :meth:`resolve`
-    method that doesn't fail with a `KeyError` but returns an
-    :class:`Undefined` object for missing variables.
-    """
-    __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
-                 'name', 'blocks', '__weakref__')
-
-    def __init__(self, environment, parent, name, blocks):
-        self.parent = parent
-        self.vars = {}
-        self.environment = environment
-        self.eval_ctx = EvalContext(self.environment, name)
-        self.exported_vars = set()
-        self.name = name
-
-        # create the initial mapping of blocks.  Whenever template inheritance
-        # takes place the runtime will update this mapping with the new blocks
-        # from the template.
-        self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
-
-    def super(self, name, current):
-        """Render a parent block."""
-        try:
-            blocks = self.blocks[name]
-            index = blocks.index(current) + 1
-            blocks[index]
-        except LookupError:
-            return self.environment.undefined('there is no parent block '
-                                              'called %r.' % name,
-                                              name='super')
-        return BlockReference(name, self, blocks, index)
-
-    def get(self, key, default=None):
-        """Returns an item from the template context, if it doesn't exist
-        `default` is returned.
-        """
-        try:
-            return self[key]
-        except KeyError:
-            return default
-
-    def resolve(self, key):
-        """Looks up a variable like `__getitem__` or `get` but returns an
-        :class:`Undefined` object with the name of the name looked up.
-        """
-        if key in self.vars:
-            return self.vars[key]
-        if key in self.parent:
-            return self.parent[key]
-        return self.environment.undefined(name=key)
-
-    def get_exported(self):
-        """Get a new dict with the exported variables."""
-        return dict((k, self.vars[k]) for k in self.exported_vars)
-
-    def get_all(self):
-        """Return a copy of the complete context as dict including the
-        exported variables.
-        """
-        return dict(self.parent, **self.vars)
-
-    @internalcode
-    def call(__self, __obj, *args, **kwargs):
-        """Call the callable with the arguments and keyword arguments
-        provided but inject the active context or environment as first
-        argument if the callable is a :func:`contextfunction` or
-        :func:`environmentfunction`.
-        """
-        if __debug__:
-            __traceback_hide__ = True
-        if isinstance(__obj, _context_function_types):
-            if getattr(__obj, 'contextfunction', 0):
-                args = (__self,) + args
-            elif getattr(__obj, 'evalcontextfunction', 0):
-                args = (__self.eval_ctx,) + args
-            elif getattr(__obj, 'environmentfunction', 0):
-                args = (__self.environment,) + args
-        try:
-            return __obj(*args, **kwargs)
-        except StopIteration:
-            return __self.environment.undefined('value was undefined because '
-                                                'a callable raised a '
-                                                'StopIteration exception')
-
-    def derived(self, locals=None):
-        """Internal helper function to create a derived context."""
-        context = new_context(self.environment, self.name, {},
-                              self.parent, True, None, locals)
-        context.eval_ctx = self.eval_ctx
-        context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
-        return context
-
-    def _all(meth):
-        proxy = lambda self: getattr(self.get_all(), meth)()
-        proxy.__doc__ = getattr(dict, meth).__doc__
-        proxy.__name__ = meth
-        return proxy
-
-    keys = _all('keys')
-    values = _all('values')
-    items = _all('items')
-
-    # not available on python 3
-    if hasattr(dict, 'iterkeys'):
-        iterkeys = _all('iterkeys')
-        itervalues = _all('itervalues')
-        iteritems = _all('iteritems')
-    del _all
-
-    def __contains__(self, name):
-        return name in self.vars or name in self.parent
-
-    def __getitem__(self, key):
-        """Lookup a variable or raise `KeyError` if the variable is
-        undefined.
-        """
-        item = self.resolve(key)
-        if isinstance(item, Undefined):
-            raise KeyError(key)
-        return item
-
-    def __repr__(self):
-        return '<%s %s of %r>' % (
-            self.__class__.__name__,
-            repr(self.get_all()),
-            self.name
-        )
-
-
-# register the context as mapping if possible
-try:
-    from collections import Mapping
-    Mapping.register(Context)
-except ImportError:
-    pass
-
-
-class BlockReference(object):
-    """One block on a template reference."""
-
-    def __init__(self, name, context, stack, depth):
-        self.name = name
-        self._context = context
-        self._stack = stack
-        self._depth = depth
-
-    @property
-    def super(self):
-        """Super the block."""
-        if self._depth + 1 >= len(self._stack):
-            return self._context.environment. \
-                undefined('there is no parent block called %r.' %
-                          self.name, name='super')
-        return BlockReference(self.name, self._context, self._stack,
-                              self._depth + 1)
-
-    @internalcode
-    def __call__(self):
-        rv = concat(self._stack[self._depth](self._context))
-        if self._context.eval_ctx.autoescape:
-            rv = Markup(rv)
-        return rv
-
-
-class LoopContext(object):
-    """A loop context for dynamic iteration."""
-
-    def __init__(self, iterable, recurse=None):
-        self._iterator = iter(iterable)
-        self._recurse = recurse
-        self.index0 = -1
-
-        # try to get the length of the iterable early.  This must be done
-        # here because there are some broken iterators around where there
-        # __len__ is the number of iterations left (i'm looking at your
-        # listreverseiterator!).
-        try:
-            self._length = len(iterable)
-        except (TypeError, AttributeError):
-            self._length = None
-
-    def cycle(self, *args):
-        """Cycles among the arguments with the current loop index."""
-        if not args:
-            raise TypeError('no items for cycling given')
-        return args[self.index0 % len(args)]
-
-    first = property(lambda x: x.index0 == 0)
-    last = property(lambda x: x.index0 + 1 == x.length)
-    index = property(lambda x: x.index0 + 1)
-    revindex = property(lambda x: x.length - x.index0)
-    revindex0 = property(lambda x: x.length - x.index)
-
-    def __len__(self):
-        return self.length
-
-    def __iter__(self):
-        return LoopContextIterator(self)
-
-    @internalcode
-    def loop(self, iterable):
-        if self._recurse is None:
-            raise TypeError('Tried to call non recursive loop.  Maybe you '
-                            "forgot the 'recursive' modifier.")
-        return self._recurse(iterable, self._recurse)
-
-    # a nifty trick to enhance the error message if someone tried to call
-    # the the loop without or with too many arguments.
-    __call__ = loop
-    del loop
-
-    @property
-    def length(self):
-        if self._length is None:
-            # if was not possible to get the length of the iterator when
-            # the loop context was created (ie: iterating over a generator)
-            # we have to convert the iterable into a sequence and use the
-            # length of that.
-            iterable = tuple(self._iterator)
-            self._iterator = iter(iterable)
-            self._length = len(iterable) + self.index0 + 1
-        return self._length
-
-    def __repr__(self):
-        return '<%s %r/%r>' % (
-            self.__class__.__name__,
-            self.index,
-            self.length
-        )
-
-
-class LoopContextIterator(object):
-    """The iterator for a loop context."""
-    __slots__ = ('context',)
-
-    def __init__(self, context):
-        self.context = context
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        ctx = self.context
-        ctx.index0 += 1
-        return next(ctx._iterator), ctx
-
-
-class Macro(object):
-    """Wraps a macro function."""
-
-    def __init__(self, environment, func, name, arguments, defaults,
-                 catch_kwargs, catch_varargs, caller):
-        self._environment = environment
-        self._func = func
-        self._argument_count = len(arguments)
-        self.name = name
-        self.arguments = arguments
-        self.defaults = defaults
-        self.catch_kwargs = catch_kwargs
-        self.catch_varargs = catch_varargs
-        self.caller = caller
-
-    @internalcode
-    def __call__(self, *args, **kwargs):
-        # try to consume the positional arguments
-        arguments = list(args[:self._argument_count])
-        off = len(arguments)
-
-        # if the number of arguments consumed is not the number of
-        # arguments expected we start filling in keyword arguments
-        # and defaults.
-        if off != self._argument_count:
-            for idx, name in enumerate(self.arguments[len(arguments):]):
-                try:
-                    value = kwargs.pop(name)
-                except KeyError:
-                    try:
-                        value = self.defaults[idx - self._argument_count + off]
-                    except IndexError:
-                        value = self._environment.undefined(
-                            'parameter %r was not provided' % name, name=name)
-                arguments.append(value)
-
-        # it's important that the order of these arguments does not change
-        # if not also changed in the compiler's `function_scoping` method.
-        # the order is caller, keyword arguments, positional arguments!
-        if self.caller:
-            caller = kwargs.pop('caller', None)
-            if caller is None:
-                caller = self._environment.undefined('No caller defined',
-                                                     name='caller')
-            arguments.append(caller)
-        if self.catch_kwargs:
-            arguments.append(kwargs)
-        elif kwargs:
-            raise TypeError('macro %r takes no keyword argument %r' %
-                            (self.name, next(iter(kwargs))))
-        if self.catch_varargs:
-            arguments.append(args[self._argument_count:])
-        elif len(args) > self._argument_count:
-            raise TypeError('macro %r takes not more than %d argument(s)' %
-                            (self.name, len(self.arguments)))
-        return self._func(*arguments)
-
-    def __repr__(self):
-        return '<%s %s>' % (
-            self.__class__.__name__,
-            self.name is None and 'anonymous' or repr(self.name)
-        )
-
-
-class Undefined(object):
-    """The default undefined type.  This undefined type can be printed and
-    iterated over, but every other access will raise an :exc:`UndefinedError`:
-
-    >>> foo = Undefined(name='foo')
-    >>> str(foo)
-    ''
-    >>> not foo
-    True
-    >>> foo + 42
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    """
-    __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
-                 '_undefined_exception')
-
-    def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
-        self._undefined_hint = hint
-        self._undefined_obj = obj
-        self._undefined_name = name
-        self._undefined_exception = exc
-
-    @internalcode
-    def _fail_with_undefined_error(self, *args, **kwargs):
-        """Regular callback function for undefined objects that raises an
-        `UndefinedError` on call.
-        """
-        if self._undefined_hint is None:
-            if self._undefined_obj is missing:
-                hint = '%r is undefined' % self._undefined_name
-            elif not isinstance(self._undefined_name, basestring):
-                hint = '%s has no element %r' % (
-                    object_type_repr(self._undefined_obj),
-                    self._undefined_name
-                )
-            else:
-                hint = '%r has no attribute %r' % (
-                    object_type_repr(self._undefined_obj),
-                    self._undefined_name
-                )
-        else:
-            hint = self._undefined_hint
-        raise self._undefined_exception(hint)
-
-    __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
-    __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
-    __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
-    __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
-    __int__ = __float__ = __complex__ = __pow__ = __rpow__ = \
-        _fail_with_undefined_error
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        return u''
-
-    def __len__(self):
-        return 0
-
-    def __iter__(self):
-        if 0:
-            yield None
-
-    def __nonzero__(self):
-        return False
-
-    def __repr__(self):
-        return 'Undefined'
-
-
-class DebugUndefined(Undefined):
-    """An undefined that returns the debug info when printed.
-
-    >>> foo = DebugUndefined(name='foo')
-    >>> str(foo)
-    '{{ foo }}'
-    >>> not foo
-    True
-    >>> foo + 42
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    """
-    __slots__ = ()
-
-    def __unicode__(self):
-        if self._undefined_hint is None:
-            if self._undefined_obj is missing:
-                return u'{{ %s }}' % self._undefined_name
-            return '{{ no such element: %s[%r] }}' % (
-                object_type_repr(self._undefined_obj),
-                self._undefined_name
-            )
-        return u'{{ undefined value printed: %s }}' % self._undefined_hint
-
-
-class StrictUndefined(Undefined):
-    """An undefined that barks on print and iteration as well as boolean
-    tests and all kinds of comparisons.  In other words: you can do nothing
-    with it except checking if it's defined using the `defined` test.
-
-    >>> foo = StrictUndefined(name='foo')
-    >>> str(foo)
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    >>> not foo
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    >>> foo + 42
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    """
-    __slots__ = ()
-    __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
-        __ne__ = __bool__ = Undefined._fail_with_undefined_error
-
-
-# remove remaining slots attributes, after the metaclass did the magic they
-# are unneeded and irritating as they contain wrong data for the subclasses.
-del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__


[55/59] [abbrv] git commit: AMBARI-7157. UI is not sending all the configs on validation (alexantonenko)

Posted by nc...@apache.org.
AMBARI-7157. UI is not sending all the configs on validation (alexantonenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/301714a3
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/301714a3
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/301714a3

Branch: refs/heads/branch-alerts-dev
Commit: 301714a3d428543500c96ec04dee8b97ae9e4b4a
Parents: fd732e3
Author: Alex Antonenko <hi...@gmail.com>
Authored: Thu Sep 4 22:53:58 2014 +0300
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Thu Sep 4 23:03:41 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/utils/blueprint.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/301714a3/ambari-web/app/utils/blueprint.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/blueprint.js b/ambari-web/app/utils/blueprint.js
index 60fda7c..d6cccb6 100644
--- a/ambari-web/app/utils/blueprint.js
+++ b/ambari-web/app/utils/blueprint.js
@@ -218,8 +218,10 @@ module.exports = {
       var config = stepConfigs.findProperty('serviceName', service.get('serviceName'));
       if (config && service.get('configTypes')) {
         Object.keys(service.get('configTypes')).forEach(function(type) {
-          configurations[type] = {
-            properties: {}
+          if(!configurations[type]){
+            configurations[type] = {
+              properties: {}
+            }
           }
         });
         config.get('configs').forEach(function(property){


[32/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/nodes.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/nodes.py b/ambari-common/src/main/python/jinja2/jinja2/nodes.py
deleted file mode 100644
index 6446c70..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/nodes.py
+++ /dev/null
@@ -1,901 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.nodes
-    ~~~~~~~~~~~~
-
-    This module implements additional nodes derived from the ast base node.
-
-    It also provides some node tree helper functions like `in_lineno` and
-    `get_nodes` used by the parser and translator in order to normalize
-    python and jinja nodes.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import operator
-from itertools import chain, izip
-from collections import deque
-from jinja2.utils import Markup, MethodType, FunctionType
-
-
-#: the types we support for context functions
-_context_function_types = (FunctionType, MethodType)
-
-
-_binop_to_func = {
-    '*':        operator.mul,
-    '/':        operator.truediv,
-    '//':       operator.floordiv,
-    '**':       operator.pow,
-    '%':        operator.mod,
-    '+':        operator.add,
-    '-':        operator.sub
-}
-
-_uaop_to_func = {
-    'not':      operator.not_,
-    '+':        operator.pos,
-    '-':        operator.neg
-}
-
-_cmpop_to_func = {
-    'eq':       operator.eq,
-    'ne':       operator.ne,
-    'gt':       operator.gt,
-    'gteq':     operator.ge,
-    'lt':       operator.lt,
-    'lteq':     operator.le,
-    'in':       lambda a, b: a in b,
-    'notin':    lambda a, b: a not in b
-}
-
-
-class Impossible(Exception):
-    """Raised if the node could not perform a requested action."""
-
-
-class NodeType(type):
-    """A metaclass for nodes that handles the field and attribute
-    inheritance.  fields and attributes from the parent class are
-    automatically forwarded to the child."""
-
-    def __new__(cls, name, bases, d):
-        for attr in 'fields', 'attributes':
-            storage = []
-            storage.extend(getattr(bases[0], attr, ()))
-            storage.extend(d.get(attr, ()))
-            assert len(bases) == 1, 'multiple inheritance not allowed'
-            assert len(storage) == len(set(storage)), 'layout conflict'
-            d[attr] = tuple(storage)
-        d.setdefault('abstract', False)
-        return type.__new__(cls, name, bases, d)
-
-
-class EvalContext(object):
-    """Holds evaluation time information.  Custom attributes can be attached
-    to it in extensions.
-    """
-
-    def __init__(self, environment, template_name=None):
-        if callable(environment.autoescape):
-            self.autoescape = environment.autoescape(template_name)
-        else:
-            self.autoescape = environment.autoescape
-        self.volatile = False
-
-    def save(self):
-        return self.__dict__.copy()
-
-    def revert(self, old):
-        self.__dict__.clear()
-        self.__dict__.update(old)
-
-
-def get_eval_context(node, ctx):
-    if ctx is None:
-        if node.environment is None:
-            raise RuntimeError('if no eval context is passed, the '
-                               'node must have an attached '
-                               'environment.')
-        return EvalContext(node.environment)
-    return ctx
-
-
-class Node(object):
-    """Baseclass for all Jinja2 nodes.  There are a number of nodes available
-    of different types.  There are three major types:
-
-    -   :class:`Stmt`: statements
-    -   :class:`Expr`: expressions
-    -   :class:`Helper`: helper nodes
-    -   :class:`Template`: the outermost wrapper node
-
-    All nodes have fields and attributes.  Fields may be other nodes, lists,
-    or arbitrary values.  Fields are passed to the constructor as regular
-    positional arguments, attributes as keyword arguments.  Each node has
-    two attributes: `lineno` (the line number of the node) and `environment`.
-    The `environment` attribute is set at the end of the parsing process for
-    all nodes automatically.
-    """
-    __metaclass__ = NodeType
-    fields = ()
-    attributes = ('lineno', 'environment')
-    abstract = True
-
-    def __init__(self, *fields, **attributes):
-        if self.abstract:
-            raise TypeError('abstract nodes are not instanciable')
-        if fields:
-            if len(fields) != len(self.fields):
-                if not self.fields:
-                    raise TypeError('%r takes 0 arguments' %
-                                    self.__class__.__name__)
-                raise TypeError('%r takes 0 or %d argument%s' % (
-                    self.__class__.__name__,
-                    len(self.fields),
-                    len(self.fields) != 1 and 's' or ''
-                ))
-            for name, arg in izip(self.fields, fields):
-                setattr(self, name, arg)
-        for attr in self.attributes:
-            setattr(self, attr, attributes.pop(attr, None))
-        if attributes:
-            raise TypeError('unknown attribute %r' %
-                            iter(attributes).next())
-
-    def iter_fields(self, exclude=None, only=None):
-        """This method iterates over all fields that are defined and yields
-        ``(key, value)`` tuples.  Per default all fields are returned, but
-        it's possible to limit that to some fields by providing the `only`
-        parameter or to exclude some using the `exclude` parameter.  Both
-        should be sets or tuples of field names.
-        """
-        for name in self.fields:
-            if (exclude is only is None) or \
-               (exclude is not None and name not in exclude) or \
-               (only is not None and name in only):
-                try:
-                    yield name, getattr(self, name)
-                except AttributeError:
-                    pass
-
-    def iter_child_nodes(self, exclude=None, only=None):
-        """Iterates over all direct child nodes of the node.  This iterates
-        over all fields and yields the values of they are nodes.  If the value
-        of a field is a list all the nodes in that list are returned.
-        """
-        for field, item in self.iter_fields(exclude, only):
-            if isinstance(item, list):
-                for n in item:
-                    if isinstance(n, Node):
-                        yield n
-            elif isinstance(item, Node):
-                yield item
-
-    def find(self, node_type):
-        """Find the first node of a given type.  If no such node exists the
-        return value is `None`.
-        """
-        for result in self.find_all(node_type):
-            return result
-
-    def find_all(self, node_type):
-        """Find all the nodes of a given type.  If the type is a tuple,
-        the check is performed for any of the tuple items.
-        """
-        for child in self.iter_child_nodes():
-            if isinstance(child, node_type):
-                yield child
-            for result in child.find_all(node_type):
-                yield result
-
-    def set_ctx(self, ctx):
-        """Reset the context of a node and all child nodes.  Per default the
-        parser will all generate nodes that have a 'load' context as it's the
-        most common one.  This method is used in the parser to set assignment
-        targets and other nodes to a store context.
-        """
-        todo = deque([self])
-        while todo:
-            node = todo.popleft()
-            if 'ctx' in node.fields:
-                node.ctx = ctx
-            todo.extend(node.iter_child_nodes())
-        return self
-
-    def set_lineno(self, lineno, override=False):
-        """Set the line numbers of the node and children."""
-        todo = deque([self])
-        while todo:
-            node = todo.popleft()
-            if 'lineno' in node.attributes:
-                if node.lineno is None or override:
-                    node.lineno = lineno
-            todo.extend(node.iter_child_nodes())
-        return self
-
-    def set_environment(self, environment):
-        """Set the environment for all nodes."""
-        todo = deque([self])
-        while todo:
-            node = todo.popleft()
-            node.environment = environment
-            todo.extend(node.iter_child_nodes())
-        return self
-
-    def __eq__(self, other):
-        return type(self) is type(other) and \
-               tuple(self.iter_fields()) == tuple(other.iter_fields())
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __repr__(self):
-        return '%s(%s)' % (
-            self.__class__.__name__,
-            ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
-                      arg in self.fields)
-        )
-
-
-class Stmt(Node):
-    """Base node for all statements."""
-    abstract = True
-
-
-class Helper(Node):
-    """Nodes that exist in a specific context only."""
-    abstract = True
-
-
-class Template(Node):
-    """Node that represents a template.  This must be the outermost node that
-    is passed to the compiler.
-    """
-    fields = ('body',)
-
-
-class Output(Stmt):
-    """A node that holds multiple expressions which are then printed out.
-    This is used both for the `print` statement and the regular template data.
-    """
-    fields = ('nodes',)
-
-
-class Extends(Stmt):
-    """Represents an extends statement."""
-    fields = ('template',)
-
-
-class For(Stmt):
-    """The for loop.  `target` is the target for the iteration (usually a
-    :class:`Name` or :class:`Tuple`), `iter` the iterable.  `body` is a list
-    of nodes that are used as loop-body, and `else_` a list of nodes for the
-    `else` block.  If no else node exists it has to be an empty list.
-
-    For filtered nodes an expression can be stored as `test`, otherwise `None`.
-    """
-    fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive')
-
-
-class If(Stmt):
-    """If `test` is true, `body` is rendered, else `else_`."""
-    fields = ('test', 'body', 'else_')
-
-
-class Macro(Stmt):
-    """A macro definition.  `name` is the name of the macro, `args` a list of
-    arguments and `defaults` a list of defaults if there are any.  `body` is
-    a list of nodes for the macro body.
-    """
-    fields = ('name', 'args', 'defaults', 'body')
-
-
-class CallBlock(Stmt):
-    """Like a macro without a name but a call instead.  `call` is called with
-    the unnamed macro as `caller` argument this node holds.
-    """
-    fields = ('call', 'args', 'defaults', 'body')
-
-
-class FilterBlock(Stmt):
-    """Node for filter sections."""
-    fields = ('body', 'filter')
-
-
-class Block(Stmt):
-    """A node that represents a block."""
-    fields = ('name', 'body', 'scoped')
-
-
-class Include(Stmt):
-    """A node that represents the include tag."""
-    fields = ('template', 'with_context', 'ignore_missing')
-
-
-class Import(Stmt):
-    """A node that represents the import tag."""
-    fields = ('template', 'target', 'with_context')
-
-
-class FromImport(Stmt):
-    """A node that represents the from import tag.  It's important to not
-    pass unsafe names to the name attribute.  The compiler translates the
-    attribute lookups directly into getattr calls and does *not* use the
-    subscript callback of the interface.  As exported variables may not
-    start with double underscores (which the parser asserts) this is not a
-    problem for regular Jinja code, but if this node is used in an extension
-    extra care must be taken.
-
-    The list of names may contain tuples if aliases are wanted.
-    """
-    fields = ('template', 'names', 'with_context')
-
-
-class ExprStmt(Stmt):
-    """A statement that evaluates an expression and discards the result."""
-    fields = ('node',)
-
-
-class Assign(Stmt):
-    """Assigns an expression to a target."""
-    fields = ('target', 'node')
-
-
-class Expr(Node):
-    """Baseclass for all expressions."""
-    abstract = True
-
-    def as_const(self, eval_ctx=None):
-        """Return the value of the expression as constant or raise
-        :exc:`Impossible` if this was not possible.
-
-        An :class:`EvalContext` can be provided, if none is given
-        a default context is created which requires the nodes to have
-        an attached environment.
-
-        .. versionchanged:: 2.4
-           the `eval_ctx` parameter was added.
-        """
-        raise Impossible()
-
-    def can_assign(self):
-        """Check if it's possible to assign something to this node."""
-        return False
-
-
-class BinExpr(Expr):
-    """Baseclass for all binary expressions."""
-    fields = ('left', 'right')
-    operator = None
-    abstract = True
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        f = _binop_to_func[self.operator]
-        try:
-            return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx))
-        except:
-            raise Impossible()
-
-
-class UnaryExpr(Expr):
-    """Baseclass for all unary expressions."""
-    fields = ('node',)
-    operator = None
-    abstract = True
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        f = _uaop_to_func[self.operator]
-        try:
-            return f(self.node.as_const(eval_ctx))
-        except:
-            raise Impossible()
-
-
-class Name(Expr):
-    """Looks up a name or stores a value in a name.
-    The `ctx` of the node can be one of the following values:
-
-    -   `store`: store a value in the name
-    -   `load`: load that name
-    -   `param`: like `store` but if the name was defined as function parameter.
-    """
-    fields = ('name', 'ctx')
-
-    def can_assign(self):
-        return self.name not in ('true', 'false', 'none',
-                                 'True', 'False', 'None')
-
-
-class Literal(Expr):
-    """Baseclass for literals."""
-    abstract = True
-
-
-class Const(Literal):
-    """All constant values.  The parser will return this node for simple
-    constants such as ``42`` or ``"foo"`` but it can be used to store more
-    complex values such as lists too.  Only constants with a safe
-    representation (objects where ``eval(repr(x)) == x`` is true).
-    """
-    fields = ('value',)
-
-    def as_const(self, eval_ctx=None):
-        return self.value
-
-    @classmethod
-    def from_untrusted(cls, value, lineno=None, environment=None):
-        """Return a const object if the value is representable as
-        constant value in the generated code, otherwise it will raise
-        an `Impossible` exception.
-        """
-        from compiler import has_safe_repr
-        if not has_safe_repr(value):
-            raise Impossible()
-        return cls(value, lineno=lineno, environment=environment)
-
-
-class TemplateData(Literal):
-    """A constant template string."""
-    fields = ('data',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile:
-            raise Impossible()
-        if eval_ctx.autoescape:
-            return Markup(self.data)
-        return self.data
-
-
-class Tuple(Literal):
-    """For loop unpacking and some other things like multiple arguments
-    for subscripts.  Like for :class:`Name` `ctx` specifies if the tuple
-    is used for loading the names or storing.
-    """
-    fields = ('items', 'ctx')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return tuple(x.as_const(eval_ctx) for x in self.items)
-
-    def can_assign(self):
-        for item in self.items:
-            if not item.can_assign():
-                return False
-        return True
-
-
-class List(Literal):
-    """Any list literal such as ``[1, 2, 3]``"""
-    fields = ('items',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return [x.as_const(eval_ctx) for x in self.items]
-
-
-class Dict(Literal):
-    """Any dict literal such as ``{1: 2, 3: 4}``.  The items must be a list of
-    :class:`Pair` nodes.
-    """
-    fields = ('items',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return dict(x.as_const(eval_ctx) for x in self.items)
-
-
-class Pair(Helper):
-    """A key, value pair for dicts."""
-    fields = ('key', 'value')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
-
-
-class Keyword(Helper):
-    """A key, value pair for keyword arguments where key is a string."""
-    fields = ('key', 'value')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.key, self.value.as_const(eval_ctx)
-
-
-class CondExpr(Expr):
-    """A conditional expression (inline if expression).  (``{{
-    foo if bar else baz }}``)
-    """
-    fields = ('test', 'expr1', 'expr2')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if self.test.as_const(eval_ctx):
-            return self.expr1.as_const(eval_ctx)
-
-        # if we evaluate to an undefined object, we better do that at runtime
-        if self.expr2 is None:
-            raise Impossible()
-
-        return self.expr2.as_const(eval_ctx)
-
-
-class Filter(Expr):
-    """This node applies a filter on an expression.  `name` is the name of
-    the filter, the rest of the fields are the same as for :class:`Call`.
-
-    If the `node` of a filter is `None` the contents of the last buffer are
-    filtered.  Buffers are created by macros and filter blocks.
-    """
-    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile or self.node is None:
-            raise Impossible()
-        # we have to be careful here because we call filter_ below.
-        # if this variable would be called filter, 2to3 would wrap the
-        # call in a list beause it is assuming we are talking about the
-        # builtin filter function here which no longer returns a list in
-        # python 3.  because of that, do not rename filter_ to filter!
-        filter_ = self.environment.filters.get(self.name)
-        if filter_ is None or getattr(filter_, 'contextfilter', False):
-            raise Impossible()
-        obj = self.node.as_const(eval_ctx)
-        args = [x.as_const(eval_ctx) for x in self.args]
-        if getattr(filter_, 'evalcontextfilter', False):
-            args.insert(0, eval_ctx)
-        elif getattr(filter_, 'environmentfilter', False):
-            args.insert(0, self.environment)
-        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
-        if self.dyn_args is not None:
-            try:
-                args.extend(self.dyn_args.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        if self.dyn_kwargs is not None:
-            try:
-                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        try:
-            return filter_(obj, *args, **kwargs)
-        except:
-            raise Impossible()
-
-
-class Test(Expr):
-    """Applies a test on an expression.  `name` is the name of the test, the
-    rest of the fields are the same as for :class:`Call`.
-    """
-    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
-
-
-class Call(Expr):
-    """Calls an expression.  `args` is a list of arguments, `kwargs` a list
-    of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
-    and `dyn_kwargs` has to be either `None` or a node that is used as
-    node for dynamic positional (``*args``) or keyword (``**kwargs``)
-    arguments.
-    """
-    fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile:
-            raise Impossible()
-        obj = self.node.as_const(eval_ctx)
-
-        # don't evaluate context functions
-        args = [x.as_const(eval_ctx) for x in self.args]
-        if isinstance(obj, _context_function_types):
-            if getattr(obj, 'contextfunction', False):
-                raise Impossible()
-            elif getattr(obj, 'evalcontextfunction', False):
-                args.insert(0, eval_ctx)
-            elif getattr(obj, 'environmentfunction', False):
-                args.insert(0, self.environment)
-
-        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
-        if self.dyn_args is not None:
-            try:
-                args.extend(self.dyn_args.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        if self.dyn_kwargs is not None:
-            try:
-                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
-            except:
-                raise Impossible()
-        try:
-            return obj(*args, **kwargs)
-        except:
-            raise Impossible()
-
-
-class Getitem(Expr):
-    """Get an attribute or item from an expression and prefer the item."""
-    fields = ('node', 'arg', 'ctx')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if self.ctx != 'load':
-            raise Impossible()
-        try:
-            return self.environment.getitem(self.node.as_const(eval_ctx),
-                                            self.arg.as_const(eval_ctx))
-        except:
-            raise Impossible()
-
-    def can_assign(self):
-        return False
-
-
-class Getattr(Expr):
-    """Get an attribute or item from an expression that is a ascii-only
-    bytestring and prefer the attribute.
-    """
-    fields = ('node', 'attr', 'ctx')
-
-    def as_const(self, eval_ctx=None):
-        if self.ctx != 'load':
-            raise Impossible()
-        try:
-            eval_ctx = get_eval_context(self, eval_ctx)
-            return self.environment.getattr(self.node.as_const(eval_ctx),
-                                            self.attr)
-        except:
-            raise Impossible()
-
-    def can_assign(self):
-        return False
-
-
-class Slice(Expr):
-    """Represents a slice object.  This must only be used as argument for
-    :class:`Subscript`.
-    """
-    fields = ('start', 'stop', 'step')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        def const(obj):
-            if obj is None:
-                return None
-            return obj.as_const(eval_ctx)
-        return slice(const(self.start), const(self.stop), const(self.step))
-
-
-class Concat(Expr):
-    """Concatenates the list of expressions provided after converting them to
-    unicode.
-    """
-    fields = ('nodes',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes)
-
-
-class Compare(Expr):
-    """Compares an expression with some other expressions.  `ops` must be a
-    list of :class:`Operand`\s.
-    """
-    fields = ('expr', 'ops')
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        result = value = self.expr.as_const(eval_ctx)
-        try:
-            for op in self.ops:
-                new_value = op.expr.as_const(eval_ctx)
-                result = _cmpop_to_func[op.op](value, new_value)
-                value = new_value
-        except:
-            raise Impossible()
-        return result
-
-
-class Operand(Helper):
-    """Holds an operator and an expression."""
-    fields = ('op', 'expr')
-
-if __debug__:
-    Operand.__doc__ += '\nThe following operators are available: ' + \
-        ', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
-                  set(_uaop_to_func) | set(_cmpop_to_func)))
-
-
-class Mul(BinExpr):
-    """Multiplies the left with the right node."""
-    operator = '*'
-
-
-class Div(BinExpr):
-    """Divides the left by the right node."""
-    operator = '/'
-
-
-class FloorDiv(BinExpr):
-    """Divides the left by the right node and truncates conver the
-    result into an integer by truncating.
-    """
-    operator = '//'
-
-
-class Add(BinExpr):
-    """Add the left to the right node."""
-    operator = '+'
-
-
-class Sub(BinExpr):
-    """Substract the right from the left node."""
-    operator = '-'
-
-
-class Mod(BinExpr):
-    """Left modulo right."""
-    operator = '%'
-
-
-class Pow(BinExpr):
-    """Left to the power of right."""
-    operator = '**'
-
-
-class And(BinExpr):
-    """Short circuited AND."""
-    operator = 'and'
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx)
-
-
-class Or(BinExpr):
-    """Short circuited OR."""
-    operator = 'or'
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx)
-
-
-class Not(UnaryExpr):
-    """Negate the expression."""
-    operator = 'not'
-
-
-class Neg(UnaryExpr):
-    """Make the expression negative."""
-    operator = '-'
-
-
-class Pos(UnaryExpr):
-    """Make the expression positive (noop for most expressions)"""
-    operator = '+'
-
-
-# Helpers for extensions
-
-
-class EnvironmentAttribute(Expr):
-    """Loads an attribute from the environment object.  This is useful for
-    extensions that want to call a callback stored on the environment.
-    """
-    fields = ('name',)
-
-
-class ExtensionAttribute(Expr):
-    """Returns the attribute of an extension bound to the environment.
-    The identifier is the identifier of the :class:`Extension`.
-
-    This node is usually constructed by calling the
-    :meth:`~jinja2.ext.Extension.attr` method on an extension.
-    """
-    fields = ('identifier', 'name')
-
-
-class ImportedName(Expr):
-    """If created with an import name the import name is returned on node
-    access.  For example ``ImportedName('cgi.escape')`` returns the `escape`
-    function from the cgi module on evaluation.  Imports are optimized by the
-    compiler so there is no need to assign them to local variables.
-    """
-    fields = ('importname',)
-
-
-class InternalName(Expr):
-    """An internal name in the compiler.  You cannot create these nodes
-    yourself but the parser provides a
-    :meth:`~jinja2.parser.Parser.free_identifier` method that creates
-    a new identifier for you.  This identifier is not available from the
-    template and is not threated specially by the compiler.
-    """
-    fields = ('name',)
-
-    def __init__(self):
-        raise TypeError('Can\'t create internal names.  Use the '
-                        '`free_identifier` method on a parser.')
-
-
-class MarkSafe(Expr):
-    """Mark the wrapped expression as safe (wrap it as `Markup`)."""
-    fields = ('expr',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        return Markup(self.expr.as_const(eval_ctx))
-
-
-class MarkSafeIfAutoescape(Expr):
-    """Mark the wrapped expression as safe (wrap it as `Markup`) but
-    only if autoescaping is active.
-
-    .. versionadded:: 2.5
-    """
-    fields = ('expr',)
-
-    def as_const(self, eval_ctx=None):
-        eval_ctx = get_eval_context(self, eval_ctx)
-        if eval_ctx.volatile:
-            raise Impossible()
-        expr = self.expr.as_const(eval_ctx)
-        if eval_ctx.autoescape:
-            return Markup(expr)
-        return expr
-
-
-class ContextReference(Expr):
-    """Returns the current template context.  It can be used like a
-    :class:`Name` node, with a ``'load'`` ctx and will return the
-    current :class:`~jinja2.runtime.Context` object.
-
-    Here an example that assigns the current template name to a
-    variable named `foo`::
-
-        Assign(Name('foo', ctx='store'),
-               Getattr(ContextReference(), 'name'))
-    """
-
-
-class Continue(Stmt):
-    """Continue a loop."""
-
-
-class Break(Stmt):
-    """Break a loop."""
-
-
-class Scope(Stmt):
-    """An artificial scope."""
-    fields = ('body',)
-
-
-class EvalContextModifier(Stmt):
-    """Modifies the eval context.  For each option that should be modified,
-    a :class:`Keyword` has to be added to the :attr:`options` list.
-
-    Example to change the `autoescape` setting::
-
-        EvalContextModifier(options=[Keyword('autoescape', Const(True))])
-    """
-    fields = ('options',)
-
-
-class ScopedEvalContextModifier(EvalContextModifier):
-    """Modifies the eval context and reverts it later.  Works exactly like
-    :class:`EvalContextModifier` but will only modify the
-    :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
-    """
-    fields = ('body',)
-
-
-# make sure nobody creates custom nodes
-def _failing_new(*args, **kwargs):
-    raise TypeError('can\'t create custom node types')
-NodeType.__new__ = staticmethod(_failing_new); del _failing_new

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/optimizer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/optimizer.py b/ambari-common/src/main/python/jinja2/jinja2/optimizer.py
deleted file mode 100644
index 00eab11..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/optimizer.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.optimizer
-    ~~~~~~~~~~~~~~~~
-
-    The jinja optimizer is currently trying to constant fold a few expressions
-    and modify the AST in place so that it should be easier to evaluate it.
-
-    Because the AST does not contain all the scoping information and the
-    compiler has to find that out, we cannot do all the optimizations we
-    want.  For example loop unrolling doesn't work because unrolled loops would
-    have a different scoping.
-
-    The solution would be a second syntax tree that has the scoping rules stored.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from jinja2 import nodes
-from jinja2.visitor import NodeTransformer
-
-
-def optimize(node, environment):
-    """The context hint can be used to perform an static optimization
-    based on the context given."""
-    optimizer = Optimizer(environment)
-    return optimizer.visit(node)
-
-
-class Optimizer(NodeTransformer):
-
-    def __init__(self, environment):
-        self.environment = environment
-
-    def visit_If(self, node):
-        """Eliminate dead code."""
-        # do not optimize ifs that have a block inside so that it doesn't
-        # break super().
-        if node.find(nodes.Block) is not None:
-            return self.generic_visit(node)
-        try:
-            val = self.visit(node.test).as_const()
-        except nodes.Impossible:
-            return self.generic_visit(node)
-        if val:
-            body = node.body
-        else:
-            body = node.else_
-        result = []
-        for node in body:
-            result.extend(self.visit_list(node))
-        return result
-
-    def fold(self, node):
-        """Do constant folding."""
-        node = self.generic_visit(node)
-        try:
-            return nodes.Const.from_untrusted(node.as_const(),
-                                              lineno=node.lineno,
-                                              environment=self.environment)
-        except nodes.Impossible:
-            return node
-
-    visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
-    visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
-    visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \
-    visit_Filter = visit_Test = visit_CondExpr = fold
-    del fold

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/parser.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/parser.py b/ambari-common/src/main/python/jinja2/jinja2/parser.py
deleted file mode 100644
index d44229a..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/parser.py
+++ /dev/null
@@ -1,896 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.parser
-    ~~~~~~~~~~~~~
-
-    Implements the template parser.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from jinja2 import nodes
-from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
-from jinja2.utils import next
-from jinja2.lexer import describe_token, describe_token_expr
-
-
-#: statements that callinto 
-_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
-                                 'macro', 'include', 'from', 'import',
-                                 'set'])
-_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
-
-
-class Parser(object):
-    """This is the central parsing class Jinja2 uses.  It's passed to
-    extensions and can be used to parse expressions or statements.
-    """
-
-    def __init__(self, environment, source, name=None, filename=None,
-                 state=None):
-        self.environment = environment
-        self.stream = environment._tokenize(source, name, filename, state)
-        self.name = name
-        self.filename = filename
-        self.closed = False
-        self.extensions = {}
-        for extension in environment.iter_extensions():
-            for tag in extension.tags:
-                self.extensions[tag] = extension.parse
-        self._last_identifier = 0
-        self._tag_stack = []
-        self._end_token_stack = []
-
-    def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
-        """Convenience method that raises `exc` with the message, passed
-        line number or last line number as well as the current name and
-        filename.
-        """
-        if lineno is None:
-            lineno = self.stream.current.lineno
-        raise exc(msg, lineno, self.name, self.filename)
-
-    def _fail_ut_eof(self, name, end_token_stack, lineno):
-        expected = []
-        for exprs in end_token_stack:
-            expected.extend(map(describe_token_expr, exprs))
-        if end_token_stack:
-            currently_looking = ' or '.join(
-                "'%s'" % describe_token_expr(expr)
-                for expr in end_token_stack[-1])
-        else:
-            currently_looking = None
-
-        if name is None:
-            message = ['Unexpected end of template.']
-        else:
-            message = ['Encountered unknown tag \'%s\'.' % name]
-
-        if currently_looking:
-            if name is not None and name in expected:
-                message.append('You probably made a nesting mistake. Jinja '
-                               'is expecting this tag, but currently looking '
-                               'for %s.' % currently_looking)
-            else:
-                message.append('Jinja was looking for the following tags: '
-                               '%s.' % currently_looking)
-
-        if self._tag_stack:
-            message.append('The innermost block that needs to be '
-                           'closed is \'%s\'.' % self._tag_stack[-1])
-
-        self.fail(' '.join(message), lineno)
-
-    def fail_unknown_tag(self, name, lineno=None):
-        """Called if the parser encounters an unknown tag.  Tries to fail
-        with a human readable error message that could help to identify
-        the problem.
-        """
-        return self._fail_ut_eof(name, self._end_token_stack, lineno)
-
-    def fail_eof(self, end_tokens=None, lineno=None):
-        """Like fail_unknown_tag but for end of template situations."""
-        stack = list(self._end_token_stack)
-        if end_tokens is not None:
-            stack.append(end_tokens)
-        return self._fail_ut_eof(None, stack, lineno)
-
-    def is_tuple_end(self, extra_end_rules=None):
-        """Are we at the end of a tuple?"""
-        if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
-            return True
-        elif extra_end_rules is not None:
-            return self.stream.current.test_any(extra_end_rules)
-        return False
-
-    def free_identifier(self, lineno=None):
-        """Return a new free identifier as :class:`~jinja2.nodes.InternalName`."""
-        self._last_identifier += 1
-        rv = object.__new__(nodes.InternalName)
-        nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
-        return rv
-
-    def parse_statement(self):
-        """Parse a single statement."""
-        token = self.stream.current
-        if token.type != 'name':
-            self.fail('tag name expected', token.lineno)
-        self._tag_stack.append(token.value)
-        pop_tag = True
-        try:
-            if token.value in _statement_keywords:
-                return getattr(self, 'parse_' + self.stream.current.value)()
-            if token.value == 'call':
-                return self.parse_call_block()
-            if token.value == 'filter':
-                return self.parse_filter_block()
-            ext = self.extensions.get(token.value)
-            if ext is not None:
-                return ext(self)
-
-            # did not work out, remove the token we pushed by accident
-            # from the stack so that the unknown tag fail function can
-            # produce a proper error message.
-            self._tag_stack.pop()
-            pop_tag = False
-            self.fail_unknown_tag(token.value, token.lineno)
-        finally:
-            if pop_tag:
-                self._tag_stack.pop()
-
-    def parse_statements(self, end_tokens, drop_needle=False):
-        """Parse multiple statements into a list until one of the end tokens
-        is reached.  This is used to parse the body of statements as it also
-        parses template data if appropriate.  The parser checks first if the
-        current token is a colon and skips it if there is one.  Then it checks
-        for the block end and parses until if one of the `end_tokens` is
-        reached.  Per default the active token in the stream at the end of
-        the call is the matched end token.  If this is not wanted `drop_needle`
-        can be set to `True` and the end token is removed.
-        """
-        # the first token may be a colon for python compatibility
-        self.stream.skip_if('colon')
-
-        # in the future it would be possible to add whole code sections
-        # by adding some sort of end of statement token and parsing those here.
-        self.stream.expect('block_end')
-        result = self.subparse(end_tokens)
-
-        # we reached the end of the template too early, the subparser
-        # does not check for this, so we do that now
-        if self.stream.current.type == 'eof':
-            self.fail_eof(end_tokens)
-
-        if drop_needle:
-            next(self.stream)
-        return result
-
-    def parse_set(self):
-        """Parse an assign statement."""
-        lineno = next(self.stream).lineno
-        target = self.parse_assign_target()
-        self.stream.expect('assign')
-        expr = self.parse_tuple()
-        return nodes.Assign(target, expr, lineno=lineno)
-
-    def parse_for(self):
-        """Parse a for loop."""
-        lineno = self.stream.expect('name:for').lineno
-        target = self.parse_assign_target(extra_end_rules=('name:in',))
-        self.stream.expect('name:in')
-        iter = self.parse_tuple(with_condexpr=False,
-                                extra_end_rules=('name:recursive',))
-        test = None
-        if self.stream.skip_if('name:if'):
-            test = self.parse_expression()
-        recursive = self.stream.skip_if('name:recursive')
-        body = self.parse_statements(('name:endfor', 'name:else'))
-        if next(self.stream).value == 'endfor':
-            else_ = []
-        else:
-            else_ = self.parse_statements(('name:endfor',), drop_needle=True)
-        return nodes.For(target, iter, body, else_, test,
-                         recursive, lineno=lineno)
-
-    def parse_if(self):
-        """Parse an if construct."""
-        node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
-        while 1:
-            node.test = self.parse_tuple(with_condexpr=False)
-            node.body = self.parse_statements(('name:elif', 'name:else',
-                                               'name:endif'))
-            token = next(self.stream)
-            if token.test('name:elif'):
-                new_node = nodes.If(lineno=self.stream.current.lineno)
-                node.else_ = [new_node]
-                node = new_node
-                continue
-            elif token.test('name:else'):
-                node.else_ = self.parse_statements(('name:endif',),
-                                                   drop_needle=True)
-            else:
-                node.else_ = []
-            break
-        return result
-
-    def parse_block(self):
-        node = nodes.Block(lineno=next(self.stream).lineno)
-        node.name = self.stream.expect('name').value
-        node.scoped = self.stream.skip_if('name:scoped')
-
-        # common problem people encounter when switching from django
-        # to jinja.  we do not support hyphens in block names, so let's
-        # raise a nicer error message in that case.
-        if self.stream.current.type == 'sub':
-            self.fail('Block names in Jinja have to be valid Python '
-                      'identifiers and may not contain hypens, use an '
-                      'underscore instead.')
-
-        node.body = self.parse_statements(('name:endblock',), drop_needle=True)
-        self.stream.skip_if('name:' + node.name)
-        return node
-
-    def parse_extends(self):
-        node = nodes.Extends(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        return node
-
-    def parse_import_context(self, node, default):
-        if self.stream.current.test_any('name:with', 'name:without') and \
-           self.stream.look().test('name:context'):
-            node.with_context = next(self.stream).value == 'with'
-            self.stream.skip()
-        else:
-            node.with_context = default
-        return node
-
-    def parse_include(self):
-        node = nodes.Include(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        if self.stream.current.test('name:ignore') and \
-           self.stream.look().test('name:missing'):
-            node.ignore_missing = True
-            self.stream.skip(2)
-        else:
-            node.ignore_missing = False
-        return self.parse_import_context(node, True)
-
-    def parse_import(self):
-        node = nodes.Import(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        self.stream.expect('name:as')
-        node.target = self.parse_assign_target(name_only=True).name
-        return self.parse_import_context(node, False)
-
-    def parse_from(self):
-        node = nodes.FromImport(lineno=next(self.stream).lineno)
-        node.template = self.parse_expression()
-        self.stream.expect('name:import')
-        node.names = []
-
-        def parse_context():
-            if self.stream.current.value in ('with', 'without') and \
-               self.stream.look().test('name:context'):
-                node.with_context = next(self.stream).value == 'with'
-                self.stream.skip()
-                return True
-            return False
-
-        while 1:
-            if node.names:
-                self.stream.expect('comma')
-            if self.stream.current.type == 'name':
-                if parse_context():
-                    break
-                target = self.parse_assign_target(name_only=True)
-                if target.name.startswith('_'):
-                    self.fail('names starting with an underline can not '
-                              'be imported', target.lineno,
-                              exc=TemplateAssertionError)
-                if self.stream.skip_if('name:as'):
-                    alias = self.parse_assign_target(name_only=True)
-                    node.names.append((target.name, alias.name))
-                else:
-                    node.names.append(target.name)
-                if parse_context() or self.stream.current.type != 'comma':
-                    break
-            else:
-                break
-        if not hasattr(node, 'with_context'):
-            node.with_context = False
-            self.stream.skip_if('comma')
-        return node
-
-    def parse_signature(self, node):
-        node.args = args = []
-        node.defaults = defaults = []
-        self.stream.expect('lparen')
-        while self.stream.current.type != 'rparen':
-            if args:
-                self.stream.expect('comma')
-            arg = self.parse_assign_target(name_only=True)
-            arg.set_ctx('param')
-            if self.stream.skip_if('assign'):
-                defaults.append(self.parse_expression())
-            args.append(arg)
-        self.stream.expect('rparen')
-
-    def parse_call_block(self):
-        node = nodes.CallBlock(lineno=next(self.stream).lineno)
-        if self.stream.current.type == 'lparen':
-            self.parse_signature(node)
-        else:
-            node.args = []
-            node.defaults = []
-
-        node.call = self.parse_expression()
-        if not isinstance(node.call, nodes.Call):
-            self.fail('expected call', node.lineno)
-        node.body = self.parse_statements(('name:endcall',), drop_needle=True)
-        return node
-
-    def parse_filter_block(self):
-        node = nodes.FilterBlock(lineno=next(self.stream).lineno)
-        node.filter = self.parse_filter(None, start_inline=True)
-        node.body = self.parse_statements(('name:endfilter',),
-                                          drop_needle=True)
-        return node
-
-    def parse_macro(self):
-        node = nodes.Macro(lineno=next(self.stream).lineno)
-        node.name = self.parse_assign_target(name_only=True).name
-        self.parse_signature(node)
-        node.body = self.parse_statements(('name:endmacro',),
-                                          drop_needle=True)
-        return node
-
-    def parse_print(self):
-        node = nodes.Output(lineno=next(self.stream).lineno)
-        node.nodes = []
-        while self.stream.current.type != 'block_end':
-            if node.nodes:
-                self.stream.expect('comma')
-            node.nodes.append(self.parse_expression())
-        return node
-
-    def parse_assign_target(self, with_tuple=True, name_only=False,
-                            extra_end_rules=None):
-        """Parse an assignment target.  As Jinja2 allows assignments to
-        tuples, this function can parse all allowed assignment targets.  Per
-        default assignments to tuples are parsed, that can be disable however
-        by setting `with_tuple` to `False`.  If only assignments to names are
-        wanted `name_only` can be set to `True`.  The `extra_end_rules`
-        parameter is forwarded to the tuple parsing function.
-        """
-        if name_only:
-            token = self.stream.expect('name')
-            target = nodes.Name(token.value, 'store', lineno=token.lineno)
-        else:
-            if with_tuple:
-                target = self.parse_tuple(simplified=True,
-                                          extra_end_rules=extra_end_rules)
-            else:
-                target = self.parse_primary()
-            target.set_ctx('store')
-        if not target.can_assign():
-            self.fail('can\'t assign to %r' % target.__class__.
-                      __name__.lower(), target.lineno)
-        return target
-
-    def parse_expression(self, with_condexpr=True):
-        """Parse an expression.  Per default all expressions are parsed, if
-        the optional `with_condexpr` parameter is set to `False` conditional
-        expressions are not parsed.
-        """
-        if with_condexpr:
-            return self.parse_condexpr()
-        return self.parse_or()
-
-    def parse_condexpr(self):
-        lineno = self.stream.current.lineno
-        expr1 = self.parse_or()
-        while self.stream.skip_if('name:if'):
-            expr2 = self.parse_or()
-            if self.stream.skip_if('name:else'):
-                expr3 = self.parse_condexpr()
-            else:
-                expr3 = None
-            expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return expr1
-
-    def parse_or(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_and()
-        while self.stream.skip_if('name:or'):
-            right = self.parse_and()
-            left = nodes.Or(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_and(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_not()
-        while self.stream.skip_if('name:and'):
-            right = self.parse_not()
-            left = nodes.And(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_not(self):
-        if self.stream.current.test('name:not'):
-            lineno = next(self.stream).lineno
-            return nodes.Not(self.parse_not(), lineno=lineno)
-        return self.parse_compare()
-
-    def parse_compare(self):
-        lineno = self.stream.current.lineno
-        expr = self.parse_add()
-        ops = []
-        while 1:
-            token_type = self.stream.current.type
-            if token_type in _compare_operators:
-                next(self.stream)
-                ops.append(nodes.Operand(token_type, self.parse_add()))
-            elif self.stream.skip_if('name:in'):
-                ops.append(nodes.Operand('in', self.parse_add()))
-            elif self.stream.current.test('name:not') and \
-                 self.stream.look().test('name:in'):
-                self.stream.skip(2)
-                ops.append(nodes.Operand('notin', self.parse_add()))
-            else:
-                break
-            lineno = self.stream.current.lineno
-        if not ops:
-            return expr
-        return nodes.Compare(expr, ops, lineno=lineno)
-
-    def parse_add(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_sub()
-        while self.stream.current.type == 'add':
-            next(self.stream)
-            right = self.parse_sub()
-            left = nodes.Add(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_sub(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_concat()
-        while self.stream.current.type == 'sub':
-            next(self.stream)
-            right = self.parse_concat()
-            left = nodes.Sub(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_concat(self):
-        lineno = self.stream.current.lineno
-        args = [self.parse_mul()]
-        while self.stream.current.type == 'tilde':
-            next(self.stream)
-            args.append(self.parse_mul())
-        if len(args) == 1:
-            return args[0]
-        return nodes.Concat(args, lineno=lineno)
-
-    def parse_mul(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_div()
-        while self.stream.current.type == 'mul':
-            next(self.stream)
-            right = self.parse_div()
-            left = nodes.Mul(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_div(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_floordiv()
-        while self.stream.current.type == 'div':
-            next(self.stream)
-            right = self.parse_floordiv()
-            left = nodes.Div(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_floordiv(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_mod()
-        while self.stream.current.type == 'floordiv':
-            next(self.stream)
-            right = self.parse_mod()
-            left = nodes.FloorDiv(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_mod(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_pow()
-        while self.stream.current.type == 'mod':
-            next(self.stream)
-            right = self.parse_pow()
-            left = nodes.Mod(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_pow(self):
-        lineno = self.stream.current.lineno
-        left = self.parse_unary()
-        while self.stream.current.type == 'pow':
-            next(self.stream)
-            right = self.parse_unary()
-            left = nodes.Pow(left, right, lineno=lineno)
-            lineno = self.stream.current.lineno
-        return left
-
-    def parse_unary(self, with_filter=True):
-        token_type = self.stream.current.type
-        lineno = self.stream.current.lineno
-        if token_type == 'sub':
-            next(self.stream)
-            node = nodes.Neg(self.parse_unary(False), lineno=lineno)
-        elif token_type == 'add':
-            next(self.stream)
-            node = nodes.Pos(self.parse_unary(False), lineno=lineno)
-        else:
-            node = self.parse_primary()
-        node = self.parse_postfix(node)
-        if with_filter:
-            node = self.parse_filter_expr(node)
-        return node
-
-    def parse_primary(self):
-        token = self.stream.current
-        if token.type == 'name':
-            if token.value in ('true', 'false', 'True', 'False'):
-                node = nodes.Const(token.value in ('true', 'True'),
-                                   lineno=token.lineno)
-            elif token.value in ('none', 'None'):
-                node = nodes.Const(None, lineno=token.lineno)
-            else:
-                node = nodes.Name(token.value, 'load', lineno=token.lineno)
-            next(self.stream)
-        elif token.type == 'string':
-            next(self.stream)
-            buf = [token.value]
-            lineno = token.lineno
-            while self.stream.current.type == 'string':
-                buf.append(self.stream.current.value)
-                next(self.stream)
-            node = nodes.Const(''.join(buf), lineno=lineno)
-        elif token.type in ('integer', 'float'):
-            next(self.stream)
-            node = nodes.Const(token.value, lineno=token.lineno)
-        elif token.type == 'lparen':
-            next(self.stream)
-            node = self.parse_tuple(explicit_parentheses=True)
-            self.stream.expect('rparen')
-        elif token.type == 'lbracket':
-            node = self.parse_list()
-        elif token.type == 'lbrace':
-            node = self.parse_dict()
-        else:
-            self.fail("unexpected '%s'" % describe_token(token), token.lineno)
-        return node
-
-    def parse_tuple(self, simplified=False, with_condexpr=True,
-                    extra_end_rules=None, explicit_parentheses=False):
-        """Works like `parse_expression` but if multiple expressions are
-        delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
-        This method could also return a regular expression instead of a tuple
-        if no commas where found.
-
-        The default parsing mode is a full tuple.  If `simplified` is `True`
-        only names and literals are parsed.  The `no_condexpr` parameter is
-        forwarded to :meth:`parse_expression`.
-
-        Because tuples do not require delimiters and may end in a bogus comma
-        an extra hint is needed that marks the end of a tuple.  For example
-        for loops support tuples between `for` and `in`.  In that case the
-        `extra_end_rules` is set to ``['name:in']``.
-
-        `explicit_parentheses` is true if the parsing was triggered by an
-        expression in parentheses.  This is used to figure out if an empty
-        tuple is a valid expression or not.
-        """
-        lineno = self.stream.current.lineno
-        if simplified:
-            parse = self.parse_primary
-        elif with_condexpr:
-            parse = self.parse_expression
-        else:
-            parse = lambda: self.parse_expression(with_condexpr=False)
-        args = []
-        is_tuple = False
-        while 1:
-            if args:
-                self.stream.expect('comma')
-            if self.is_tuple_end(extra_end_rules):
-                break
-            args.append(parse())
-            if self.stream.current.type == 'comma':
-                is_tuple = True
-            else:
-                break
-            lineno = self.stream.current.lineno
-
-        if not is_tuple:
-            if args:
-                return args[0]
-
-            # if we don't have explicit parentheses, an empty tuple is
-            # not a valid expression.  This would mean nothing (literally
-            # nothing) in the spot of an expression would be an empty
-            # tuple.
-            if not explicit_parentheses:
-                self.fail('Expected an expression, got \'%s\'' %
-                          describe_token(self.stream.current))
-
-        return nodes.Tuple(args, 'load', lineno=lineno)
-
-    def parse_list(self):
-        token = self.stream.expect('lbracket')
-        items = []
-        while self.stream.current.type != 'rbracket':
-            if items:
-                self.stream.expect('comma')
-            if self.stream.current.type == 'rbracket':
-                break
-            items.append(self.parse_expression())
-        self.stream.expect('rbracket')
-        return nodes.List(items, lineno=token.lineno)
-
-    def parse_dict(self):
-        token = self.stream.expect('lbrace')
-        items = []
-        while self.stream.current.type != 'rbrace':
-            if items:
-                self.stream.expect('comma')
-            if self.stream.current.type == 'rbrace':
-                break
-            key = self.parse_expression()
-            self.stream.expect('colon')
-            value = self.parse_expression()
-            items.append(nodes.Pair(key, value, lineno=key.lineno))
-        self.stream.expect('rbrace')
-        return nodes.Dict(items, lineno=token.lineno)
-
-    def parse_postfix(self, node):
-        while 1:
-            token_type = self.stream.current.type
-            if token_type == 'dot' or token_type == 'lbracket':
-                node = self.parse_subscript(node)
-            # calls are valid both after postfix expressions (getattr
-            # and getitem) as well as filters and tests
-            elif token_type == 'lparen':
-                node = self.parse_call(node)
-            else:
-                break
-        return node
-
-    def parse_filter_expr(self, node):
-        while 1:
-            token_type = self.stream.current.type
-            if token_type == 'pipe':
-                node = self.parse_filter(node)
-            elif token_type == 'name' and self.stream.current.value == 'is':
-                node = self.parse_test(node)
-            # calls are valid both after postfix expressions (getattr
-            # and getitem) as well as filters and tests
-            elif token_type == 'lparen':
-                node = self.parse_call(node)
-            else:
-                break
-        return node
-
-    def parse_subscript(self, node):
-        token = next(self.stream)
-        if token.type == 'dot':
-            attr_token = self.stream.current
-            next(self.stream)
-            if attr_token.type == 'name':
-                return nodes.Getattr(node, attr_token.value, 'load',
-                                     lineno=token.lineno)
-            elif attr_token.type != 'integer':
-                self.fail('expected name or number', attr_token.lineno)
-            arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
-            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
-        if token.type == 'lbracket':
-            priority_on_attribute = False
-            args = []
-            while self.stream.current.type != 'rbracket':
-                if args:
-                    self.stream.expect('comma')
-                args.append(self.parse_subscribed())
-            self.stream.expect('rbracket')
-            if len(args) == 1:
-                arg = args[0]
-            else:
-                arg = nodes.Tuple(args, 'load', lineno=token.lineno)
-            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
-        self.fail('expected subscript expression', self.lineno)
-
-    def parse_subscribed(self):
-        lineno = self.stream.current.lineno
-
-        if self.stream.current.type == 'colon':
-            next(self.stream)
-            args = [None]
-        else:
-            node = self.parse_expression()
-            if self.stream.current.type != 'colon':
-                return node
-            next(self.stream)
-            args = [node]
-
-        if self.stream.current.type == 'colon':
-            args.append(None)
-        elif self.stream.current.type not in ('rbracket', 'comma'):
-            args.append(self.parse_expression())
-        else:
-            args.append(None)
-
-        if self.stream.current.type == 'colon':
-            next(self.stream)
-            if self.stream.current.type not in ('rbracket', 'comma'):
-                args.append(self.parse_expression())
-            else:
-                args.append(None)
-        else:
-            args.append(None)
-
-        return nodes.Slice(lineno=lineno, *args)
-
-    def parse_call(self, node):
-        token = self.stream.expect('lparen')
-        args = []
-        kwargs = []
-        dyn_args = dyn_kwargs = None
-        require_comma = False
-
-        def ensure(expr):
-            if not expr:
-                self.fail('invalid syntax for function call expression',
-                          token.lineno)
-
-        while self.stream.current.type != 'rparen':
-            if require_comma:
-                self.stream.expect('comma')
-                # support for trailing comma
-                if self.stream.current.type == 'rparen':
-                    break
-            if self.stream.current.type == 'mul':
-                ensure(dyn_args is None and dyn_kwargs is None)
-                next(self.stream)
-                dyn_args = self.parse_expression()
-            elif self.stream.current.type == 'pow':
-                ensure(dyn_kwargs is None)
-                next(self.stream)
-                dyn_kwargs = self.parse_expression()
-            else:
-                ensure(dyn_args is None and dyn_kwargs is None)
-                if self.stream.current.type == 'name' and \
-                    self.stream.look().type == 'assign':
-                    key = self.stream.current.value
-                    self.stream.skip(2)
-                    value = self.parse_expression()
-                    kwargs.append(nodes.Keyword(key, value,
-                                                lineno=value.lineno))
-                else:
-                    ensure(not kwargs)
-                    args.append(self.parse_expression())
-
-            require_comma = True
-        self.stream.expect('rparen')
-
-        if node is None:
-            return args, kwargs, dyn_args, dyn_kwargs
-        return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
-                          lineno=token.lineno)
-
-    def parse_filter(self, node, start_inline=False):
-        while self.stream.current.type == 'pipe' or start_inline:
-            if not start_inline:
-                next(self.stream)
-            token = self.stream.expect('name')
-            name = token.value
-            while self.stream.current.type == 'dot':
-                next(self.stream)
-                name += '.' + self.stream.expect('name').value
-            if self.stream.current.type == 'lparen':
-                args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
-            else:
-                args = []
-                kwargs = []
-                dyn_args = dyn_kwargs = None
-            node = nodes.Filter(node, name, args, kwargs, dyn_args,
-                                dyn_kwargs, lineno=token.lineno)
-            start_inline = False
-        return node
-
-    def parse_test(self, node):
-        token = next(self.stream)
-        if self.stream.current.test('name:not'):
-            next(self.stream)
-            negated = True
-        else:
-            negated = False
-        name = self.stream.expect('name').value
-        while self.stream.current.type == 'dot':
-            next(self.stream)
-            name += '.' + self.stream.expect('name').value
-        dyn_args = dyn_kwargs = None
-        kwargs = []
-        if self.stream.current.type == 'lparen':
-            args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
-        elif self.stream.current.type in ('name', 'string', 'integer',
-                                          'float', 'lparen', 'lbracket',
-                                          'lbrace') and not \
-             self.stream.current.test_any('name:else', 'name:or',
-                                          'name:and'):
-            if self.stream.current.test('name:is'):
-                self.fail('You cannot chain multiple tests with is')
-            args = [self.parse_expression()]
-        else:
-            args = []
-        node = nodes.Test(node, name, args, kwargs, dyn_args,
-                          dyn_kwargs, lineno=token.lineno)
-        if negated:
-            node = nodes.Not(node, lineno=token.lineno)
-        return node
-
-    def subparse(self, end_tokens=None):
-        body = []
-        data_buffer = []
-        add_data = data_buffer.append
-
-        if end_tokens is not None:
-            self._end_token_stack.append(end_tokens)
-
-        def flush_data():
-            if data_buffer:
-                lineno = data_buffer[0].lineno
-                body.append(nodes.Output(data_buffer[:], lineno=lineno))
-                del data_buffer[:]
-
-        try:
-            while self.stream:
-                token = self.stream.current
-                if token.type == 'data':
-                    if token.value:
-                        add_data(nodes.TemplateData(token.value,
-                                                    lineno=token.lineno))
-                    next(self.stream)
-                elif token.type == 'variable_begin':
-                    next(self.stream)
-                    add_data(self.parse_tuple(with_condexpr=True))
-                    self.stream.expect('variable_end')
-                elif token.type == 'block_begin':
-                    flush_data()
-                    next(self.stream)
-                    if end_tokens is not None and \
-                       self.stream.current.test_any(*end_tokens):
-                        return body
-                    rv = self.parse_statement()
-                    if isinstance(rv, list):
-                        body.extend(rv)
-                    else:
-                        body.append(rv)
-                    self.stream.expect('block_end')
-                else:
-                    raise AssertionError('internal parsing error')
-
-            flush_data()
-        finally:
-            if end_tokens is not None:
-                self._end_token_stack.pop()
-
-        return body
-
-    def parse(self):
-        """Parse the whole template into a `Template` node."""
-        result = nodes.Template(self.subparse(), lineno=1)
-        result.set_environment(self.environment)
-        return result

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/runtime.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/runtime.py b/ambari-common/src/main/python/jinja2/jinja2/runtime.py
deleted file mode 100644
index 6fea3aa..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/runtime.py
+++ /dev/null
@@ -1,544 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.runtime
-    ~~~~~~~~~~~~~~
-
-    Runtime helpers.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-import sys
-from itertools import chain, imap
-from jinja2.nodes import EvalContext, _context_function_types
-from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
-     concat, internalcode, next, object_type_repr
-from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
-     TemplateNotFound
-
-
-# these variables are exported to the template runtime
-__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
-           'TemplateRuntimeError', 'missing', 'concat', 'escape',
-           'markup_join', 'unicode_join', 'to_string', 'identity',
-           'TemplateNotFound']
-
-#: the name of the function that is used to convert something into
-#: a string.  2to3 will adopt that automatically and the generated
-#: code can take advantage of it.
-to_string = unicode
-
-#: the identity function.  Useful for certain things in the environment
-identity = lambda x: x
-
-
-def markup_join(seq):
-    """Concatenation that escapes if necessary and converts to unicode."""
-    buf = []
-    iterator = imap(soft_unicode, seq)
-    for arg in iterator:
-        buf.append(arg)
-        if hasattr(arg, '__html__'):
-            return Markup(u'').join(chain(buf, iterator))
-    return concat(buf)
-
-
-def unicode_join(seq):
-    """Simple args to unicode conversion and concatenation."""
-    return concat(imap(unicode, seq))
-
-
-def new_context(environment, template_name, blocks, vars=None,
-                shared=None, globals=None, locals=None):
-    """Internal helper to for context creation."""
-    if vars is None:
-        vars = {}
-    if shared:
-        parent = vars
-    else:
-        parent = dict(globals or (), **vars)
-    if locals:
-        # if the parent is shared a copy should be created because
-        # we don't want to modify the dict passed
-        if shared:
-            parent = dict(parent)
-        for key, value in locals.iteritems():
-            if key[:2] == 'l_' and value is not missing:
-                parent[key[2:]] = value
-    return Context(environment, parent, template_name, blocks)
-
-
-class TemplateReference(object):
-    """The `self` in templates."""
-
-    def __init__(self, context):
-        self.__context = context
-
-    def __getitem__(self, name):
-        blocks = self.__context.blocks[name]
-        wrap = self.__context.eval_ctx.autoescape and \
-               Markup or (lambda x: x)
-        return BlockReference(name, self.__context, blocks, 0)
-
-    def __repr__(self):
-        return '<%s %r>' % (
-            self.__class__.__name__,
-            self.__context.name
-        )
-
-
-class Context(object):
-    """The template context holds the variables of a template.  It stores the
-    values passed to the template and also the names the template exports.
-    Creating instances is neither supported nor useful as it's created
-    automatically at various stages of the template evaluation and should not
-    be created by hand.
-
-    The context is immutable.  Modifications on :attr:`parent` **must not**
-    happen and modifications on :attr:`vars` are allowed from generated
-    template code only.  Template filters and global functions marked as
-    :func:`contextfunction`\s get the active context passed as first argument
-    and are allowed to access the context read-only.
-
-    The template context supports read only dict operations (`get`,
-    `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
-    `__getitem__`, `__contains__`).  Additionally there is a :meth:`resolve`
-    method that doesn't fail with a `KeyError` but returns an
-    :class:`Undefined` object for missing variables.
-    """
-    __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
-                 'name', 'blocks', '__weakref__')
-
-    def __init__(self, environment, parent, name, blocks):
-        self.parent = parent
-        self.vars = {}
-        self.environment = environment
-        self.eval_ctx = EvalContext(self.environment, name)
-        self.exported_vars = set()
-        self.name = name
-
-        # create the initial mapping of blocks.  Whenever template inheritance
-        # takes place the runtime will update this mapping with the new blocks
-        # from the template.
-        self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
-
-    def super(self, name, current):
-        """Render a parent block."""
-        try:
-            blocks = self.blocks[name]
-            index = blocks.index(current) + 1
-            blocks[index]
-        except LookupError:
-            return self.environment.undefined('there is no parent block '
-                                              'called %r.' % name,
-                                              name='super')
-        return BlockReference(name, self, blocks, index)
-
-    def get(self, key, default=None):
-        """Returns an item from the template context, if it doesn't exist
-        `default` is returned.
-        """
-        try:
-            return self[key]
-        except KeyError:
-            return default
-
-    def resolve(self, key):
-        """Looks up a variable like `__getitem__` or `get` but returns an
-        :class:`Undefined` object with the name of the name looked up.
-        """
-        if key in self.vars:
-            return self.vars[key]
-        if key in self.parent:
-            return self.parent[key]
-        return self.environment.undefined(name=key)
-
-    def get_exported(self):
-        """Get a new dict with the exported variables."""
-        return dict((k, self.vars[k]) for k in self.exported_vars)
-
-    def get_all(self):
-        """Return a copy of the complete context as dict including the
-        exported variables.
-        """
-        return dict(self.parent, **self.vars)
-
-    @internalcode
-    def call(__self, __obj, *args, **kwargs):
-        """Call the callable with the arguments and keyword arguments
-        provided but inject the active context or environment as first
-        argument if the callable is a :func:`contextfunction` or
-        :func:`environmentfunction`.
-        """
-        if __debug__:
-            __traceback_hide__ = True
-        if isinstance(__obj, _context_function_types):
-            if getattr(__obj, 'contextfunction', 0):
-                args = (__self,) + args
-            elif getattr(__obj, 'evalcontextfunction', 0):
-                args = (__self.eval_ctx,) + args
-            elif getattr(__obj, 'environmentfunction', 0):
-                args = (__self.environment,) + args
-        try:
-            return __obj(*args, **kwargs)
-        except StopIteration:
-            return __self.environment.undefined('value was undefined because '
-                                                'a callable raised a '
-                                                'StopIteration exception')
-
-    def derived(self, locals=None):
-        """Internal helper function to create a derived context."""
-        context = new_context(self.environment, self.name, {},
-                              self.parent, True, None, locals)
-        context.eval_ctx = self.eval_ctx
-        context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
-        return context
-
-    def _all(meth):
-        proxy = lambda self: getattr(self.get_all(), meth)()
-        proxy.__doc__ = getattr(dict, meth).__doc__
-        proxy.__name__ = meth
-        return proxy
-
-    keys = _all('keys')
-    values = _all('values')
-    items = _all('items')
-
-    # not available on python 3
-    if hasattr(dict, 'iterkeys'):
-        iterkeys = _all('iterkeys')
-        itervalues = _all('itervalues')
-        iteritems = _all('iteritems')
-    del _all
-
-    def __contains__(self, name):
-        return name in self.vars or name in self.parent
-
-    def __getitem__(self, key):
-        """Lookup a variable or raise `KeyError` if the variable is
-        undefined.
-        """
-        item = self.resolve(key)
-        if isinstance(item, Undefined):
-            raise KeyError(key)
-        return item
-
-    def __repr__(self):
-        return '<%s %s of %r>' % (
-            self.__class__.__name__,
-            repr(self.get_all()),
-            self.name
-        )
-
-
-# register the context as mapping if possible
-try:
-    from collections import Mapping
-    Mapping.register(Context)
-except ImportError:
-    pass
-
-
-class BlockReference(object):
-    """One block on a template reference."""
-
-    def __init__(self, name, context, stack, depth):
-        self.name = name
-        self._context = context
-        self._stack = stack
-        self._depth = depth
-
-    @property
-    def super(self):
-        """Super the block."""
-        if self._depth + 1 >= len(self._stack):
-            return self._context.environment. \
-                undefined('there is no parent block called %r.' %
-                          self.name, name='super')
-        return BlockReference(self.name, self._context, self._stack,
-                              self._depth + 1)
-
-    @internalcode
-    def __call__(self):
-        rv = concat(self._stack[self._depth](self._context))
-        if self._context.eval_ctx.autoescape:
-            rv = Markup(rv)
-        return rv
-
-
-class LoopContext(object):
-    """A loop context for dynamic iteration."""
-
-    def __init__(self, iterable, recurse=None):
-        self._iterator = iter(iterable)
-        self._recurse = recurse
-        self.index0 = -1
-
-        # try to get the length of the iterable early.  This must be done
-        # here because there are some broken iterators around where there
-        # __len__ is the number of iterations left (i'm looking at your
-        # listreverseiterator!).
-        try:
-            self._length = len(iterable)
-        except (TypeError, AttributeError):
-            self._length = None
-
-    def cycle(self, *args):
-        """Cycles among the arguments with the current loop index."""
-        if not args:
-            raise TypeError('no items for cycling given')
-        return args[self.index0 % len(args)]
-
-    first = property(lambda x: x.index0 == 0)
-    last = property(lambda x: x.index0 + 1 == x.length)
-    index = property(lambda x: x.index0 + 1)
-    revindex = property(lambda x: x.length - x.index0)
-    revindex0 = property(lambda x: x.length - x.index)
-
-    def __len__(self):
-        return self.length
-
-    def __iter__(self):
-        return LoopContextIterator(self)
-
-    @internalcode
-    def loop(self, iterable):
-        if self._recurse is None:
-            raise TypeError('Tried to call non recursive loop.  Maybe you '
-                            "forgot the 'recursive' modifier.")
-        return self._recurse(iterable, self._recurse)
-
-    # a nifty trick to enhance the error message if someone tried to call
-    # the the loop without or with too many arguments.
-    __call__ = loop
-    del loop
-
-    @property
-    def length(self):
-        if self._length is None:
-            # if was not possible to get the length of the iterator when
-            # the loop context was created (ie: iterating over a generator)
-            # we have to convert the iterable into a sequence and use the
-            # length of that.
-            iterable = tuple(self._iterator)
-            self._iterator = iter(iterable)
-            self._length = len(iterable) + self.index0 + 1
-        return self._length
-
-    def __repr__(self):
-        return '<%s %r/%r>' % (
-            self.__class__.__name__,
-            self.index,
-            self.length
-        )
-
-
-class LoopContextIterator(object):
-    """The iterator for a loop context."""
-    __slots__ = ('context',)
-
-    def __init__(self, context):
-        self.context = context
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        ctx = self.context
-        ctx.index0 += 1
-        return next(ctx._iterator), ctx
-
-
-class Macro(object):
-    """Wraps a macro function."""
-
-    def __init__(self, environment, func, name, arguments, defaults,
-                 catch_kwargs, catch_varargs, caller):
-        self._environment = environment
-        self._func = func
-        self._argument_count = len(arguments)
-        self.name = name
-        self.arguments = arguments
-        self.defaults = defaults
-        self.catch_kwargs = catch_kwargs
-        self.catch_varargs = catch_varargs
-        self.caller = caller
-
-    @internalcode
-    def __call__(self, *args, **kwargs):
-        # try to consume the positional arguments
-        arguments = list(args[:self._argument_count])
-        off = len(arguments)
-
-        # if the number of arguments consumed is not the number of
-        # arguments expected we start filling in keyword arguments
-        # and defaults.
-        if off != self._argument_count:
-            for idx, name in enumerate(self.arguments[len(arguments):]):
-                try:
-                    value = kwargs.pop(name)
-                except KeyError:
-                    try:
-                        value = self.defaults[idx - self._argument_count + off]
-                    except IndexError:
-                        value = self._environment.undefined(
-                            'parameter %r was not provided' % name, name=name)
-                arguments.append(value)
-
-        # it's important that the order of these arguments does not change
-        # if not also changed in the compiler's `function_scoping` method.
-        # the order is caller, keyword arguments, positional arguments!
-        if self.caller:
-            caller = kwargs.pop('caller', None)
-            if caller is None:
-                caller = self._environment.undefined('No caller defined',
-                                                     name='caller')
-            arguments.append(caller)
-        if self.catch_kwargs:
-            arguments.append(kwargs)
-        elif kwargs:
-            raise TypeError('macro %r takes no keyword argument %r' %
-                            (self.name, next(iter(kwargs))))
-        if self.catch_varargs:
-            arguments.append(args[self._argument_count:])
-        elif len(args) > self._argument_count:
-            raise TypeError('macro %r takes not more than %d argument(s)' %
-                            (self.name, len(self.arguments)))
-        return self._func(*arguments)
-
-    def __repr__(self):
-        return '<%s %s>' % (
-            self.__class__.__name__,
-            self.name is None and 'anonymous' or repr(self.name)
-        )
-
-
-class Undefined(object):
-    """The default undefined type.  This undefined type can be printed and
-    iterated over, but every other access will raise an :exc:`UndefinedError`:
-
-    >>> foo = Undefined(name='foo')
-    >>> str(foo)
-    ''
-    >>> not foo
-    True
-    >>> foo + 42
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    """
-    __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
-                 '_undefined_exception')
-
-    def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
-        self._undefined_hint = hint
-        self._undefined_obj = obj
-        self._undefined_name = name
-        self._undefined_exception = exc
-
-    @internalcode
-    def _fail_with_undefined_error(self, *args, **kwargs):
-        """Regular callback function for undefined objects that raises an
-        `UndefinedError` on call.
-        """
-        if self._undefined_hint is None:
-            if self._undefined_obj is missing:
-                hint = '%r is undefined' % self._undefined_name
-            elif not isinstance(self._undefined_name, basestring):
-                hint = '%s has no element %r' % (
-                    object_type_repr(self._undefined_obj),
-                    self._undefined_name
-                )
-            else:
-                hint = '%r has no attribute %r' % (
-                    object_type_repr(self._undefined_obj),
-                    self._undefined_name
-                )
-        else:
-            hint = self._undefined_hint
-        raise self._undefined_exception(hint)
-
-    __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
-    __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
-    __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
-    __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
-    __int__ = __float__ = __complex__ = __pow__ = __rpow__ = \
-        _fail_with_undefined_error
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        return u''
-
-    def __len__(self):
-        return 0
-
-    def __iter__(self):
-        if 0:
-            yield None
-
-    def __nonzero__(self):
-        return False
-
-    def __repr__(self):
-        return 'Undefined'
-
-
-class DebugUndefined(Undefined):
-    """An undefined that returns the debug info when printed.
-
-    >>> foo = DebugUndefined(name='foo')
-    >>> str(foo)
-    '{{ foo }}'
-    >>> not foo
-    True
-    >>> foo + 42
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    """
-    __slots__ = ()
-
-    def __unicode__(self):
-        if self._undefined_hint is None:
-            if self._undefined_obj is missing:
-                return u'{{ %s }}' % self._undefined_name
-            return '{{ no such element: %s[%r] }}' % (
-                object_type_repr(self._undefined_obj),
-                self._undefined_name
-            )
-        return u'{{ undefined value printed: %s }}' % self._undefined_hint
-
-
-class StrictUndefined(Undefined):
-    """An undefined that barks on print and iteration as well as boolean
-    tests and all kinds of comparisons.  In other words: you can do nothing
-    with it except checking if it's defined using the `defined` test.
-
-    >>> foo = StrictUndefined(name='foo')
-    >>> str(foo)
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    >>> not foo
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    >>> foo + 42
-    Traceback (most recent call last):
-      ...
-    UndefinedError: 'foo' is undefined
-    """
-    __slots__ = ()
-    __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
-        __ne__ = __bool__ = Undefined._fail_with_undefined_error
-
-
-# remove remaining slots attributes, after the metaclass did the magic they
-# are unneeded and irritating as they contain wrong data for the subclasses.
-del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__


[26/59] [abbrv] git commit: AMBARI-7143. Current icon has restart indicator even when not required.(XI WANG)

Posted by nc...@apache.org.
AMBARI-7143. Current icon has restart indicator even when not required.(XI WANG)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ce77f0e7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ce77f0e7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ce77f0e7

Branch: refs/heads/branch-alerts-dev
Commit: ce77f0e7f4f18e1feb6b3f1b156517e97381c67f
Parents: b68d3fa
Author: Xi Wang <xi...@apache.org>
Authored: Wed Sep 3 17:11:19 2014 -0700
Committer: Xi Wang <xi...@apache.org>
Committed: Wed Sep 3 17:17:56 2014 -0700

----------------------------------------------------------------------
 ambari-web/app/templates/common/configs/config_history_flow.hbs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77f0e7/ambari-web/app/templates/common/configs/config_history_flow.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/config_history_flow.hbs b/ambari-web/app/templates/common/configs/config_history_flow.hbs
index ec79fc2..fb08584 100644
--- a/ambari-web/app/templates/common/configs/config_history_flow.hbs
+++ b/ambari-web/app/templates/common/configs/config_history_flow.hbs
@@ -31,7 +31,7 @@
               {{#if serviceVersion.isCurrent}}
                 <span class="label label-success">
                 {{t common.current}}
-                <i {{bindAttr class=":icon-refresh :restart-required-service view.serviceVersion.isRestartRequired::hidden"}}></i>
+                <i {{bindAttr class=":icon-refresh :restart-required-service serviceVersion.isRestartRequired::hidden"}}></i>
               </span>
               {{/if}}
             </div>


[06/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/bccache.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/bccache.py b/ambari-common/src/main/python/jinja2/jinja2/bccache.py
new file mode 100644
index 0000000..1e2236c
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/bccache.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.bccache
+    ~~~~~~~~~~~~~~
+
+    This module implements the bytecode cache system Jinja is optionally
+    using.  This is useful if you have very complex template situations and
+    the compiliation of all those templates slow down your application too
+    much.
+
+    Situations where this is useful are often forking web applications that
+    are initialized on the first request.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from os import path, listdir
+import marshal
+import tempfile
+import cPickle as pickle
+import fnmatch
+from cStringIO import StringIO
+try:
+    from hashlib import sha1
+except ImportError:
+    from sha import new as sha1
+from jinja2.utils import open_if_exists
+
+
+bc_version = 1
+bc_magic = 'j2'.encode('ascii') + pickle.dumps(bc_version, 2)
+
+
+class Bucket(object):
+    """Buckets are used to store the bytecode for one template.  It's created
+    and initialized by the bytecode cache and passed to the loading functions.
+
+    The buckets get an internal checksum from the cache assigned and use this
+    to automatically reject outdated cache material.  Individual bytecode
+    cache subclasses don't have to care about cache invalidation.
+    """
+
+    def __init__(self, environment, key, checksum):
+        self.environment = environment
+        self.key = key
+        self.checksum = checksum
+        self.reset()
+
+    def reset(self):
+        """Resets the bucket (unloads the bytecode)."""
+        self.code = None
+
+    def load_bytecode(self, f):
+        """Loads bytecode from a file or file like object."""
+        # make sure the magic header is correct
+        magic = f.read(len(bc_magic))
+        if magic != bc_magic:
+            self.reset()
+            return
+        # the source code of the file changed, we need to reload
+        checksum = pickle.load(f)
+        if self.checksum != checksum:
+            self.reset()
+            return
+        # now load the code.  Because marshal is not able to load
+        # from arbitrary streams we have to work around that
+        if isinstance(f, file):
+            self.code = marshal.load(f)
+        else:
+            self.code = marshal.loads(f.read())
+
+    def write_bytecode(self, f):
+        """Dump the bytecode into the file or file like object passed."""
+        if self.code is None:
+            raise TypeError('can\'t write empty bucket')
+        f.write(bc_magic)
+        pickle.dump(self.checksum, f, 2)
+        if isinstance(f, file):
+            marshal.dump(self.code, f)
+        else:
+            f.write(marshal.dumps(self.code))
+
+    def bytecode_from_string(self, string):
+        """Load bytecode from a string."""
+        self.load_bytecode(StringIO(string))
+
+    def bytecode_to_string(self):
+        """Return the bytecode as string."""
+        out = StringIO()
+        self.write_bytecode(out)
+        return out.getvalue()
+
+
+class BytecodeCache(object):
+    """To implement your own bytecode cache you have to subclass this class
+    and override :meth:`load_bytecode` and :meth:`dump_bytecode`.  Both of
+    these methods are passed a :class:`~jinja2.bccache.Bucket`.
+
+    A very basic bytecode cache that saves the bytecode on the file system::
+
+        from os import path
+
+        class MyCache(BytecodeCache):
+
+            def __init__(self, directory):
+                self.directory = directory
+
+            def load_bytecode(self, bucket):
+                filename = path.join(self.directory, bucket.key)
+                if path.exists(filename):
+                    with open(filename, 'rb') as f:
+                        bucket.load_bytecode(f)
+
+            def dump_bytecode(self, bucket):
+                filename = path.join(self.directory, bucket.key)
+                with open(filename, 'wb') as f:
+                    bucket.write_bytecode(f)
+
+    A more advanced version of a filesystem based bytecode cache is part of
+    Jinja2.
+    """
+
+    def load_bytecode(self, bucket):
+        """Subclasses have to override this method to load bytecode into a
+        bucket.  If they are not able to find code in the cache for the
+        bucket, it must not do anything.
+        """
+        raise NotImplementedError()
+
+    def dump_bytecode(self, bucket):
+        """Subclasses have to override this method to write the bytecode
+        from a bucket back to the cache.  If it unable to do so it must not
+        fail silently but raise an exception.
+        """
+        raise NotImplementedError()
+
+    def clear(self):
+        """Clears the cache.  This method is not used by Jinja2 but should be
+        implemented to allow applications to clear the bytecode cache used
+        by a particular environment.
+        """
+
+    def get_cache_key(self, name, filename=None):
+        """Returns the unique hash key for this template name."""
+        hash = sha1(name.encode('utf-8'))
+        if filename is not None:
+            if isinstance(filename, unicode):
+                filename = filename.encode('utf-8')
+            hash.update('|' + filename)
+        return hash.hexdigest()
+
+    def get_source_checksum(self, source):
+        """Returns a checksum for the source."""
+        return sha1(source.encode('utf-8')).hexdigest()
+
+    def get_bucket(self, environment, name, filename, source):
+        """Return a cache bucket for the given template.  All arguments are
+        mandatory but filename may be `None`.
+        """
+        key = self.get_cache_key(name, filename)
+        checksum = self.get_source_checksum(source)
+        bucket = Bucket(environment, key, checksum)
+        self.load_bytecode(bucket)
+        return bucket
+
+    def set_bucket(self, bucket):
+        """Put the bucket into the cache."""
+        self.dump_bytecode(bucket)
+
+
+class FileSystemBytecodeCache(BytecodeCache):
+    """A bytecode cache that stores bytecode on the filesystem.  It accepts
+    two arguments: The directory where the cache items are stored and a
+    pattern string that is used to build the filename.
+
+    If no directory is specified the system temporary items folder is used.
+
+    The pattern can be used to have multiple separate caches operate on the
+    same directory.  The default pattern is ``'__jinja2_%s.cache'``.  ``%s``
+    is replaced with the cache key.
+
+    >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
+
+    This bytecode cache supports clearing of the cache using the clear method.
+    """
+
+    def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
+        if directory is None:
+            directory = tempfile.gettempdir()
+        self.directory = directory
+        self.pattern = pattern
+
+    def _get_cache_filename(self, bucket):
+        return path.join(self.directory, self.pattern % bucket.key)
+
+    def load_bytecode(self, bucket):
+        f = open_if_exists(self._get_cache_filename(bucket), 'rb')
+        if f is not None:
+            try:
+                bucket.load_bytecode(f)
+            finally:
+                f.close()
+
+    def dump_bytecode(self, bucket):
+        f = open(self._get_cache_filename(bucket), 'wb')
+        try:
+            bucket.write_bytecode(f)
+        finally:
+            f.close()
+
+    def clear(self):
+        # imported lazily here because google app-engine doesn't support
+        # write access on the file system and the function does not exist
+        # normally.
+        from os import remove
+        files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
+        for filename in files:
+            try:
+                remove(path.join(self.directory, filename))
+            except OSError:
+                pass
+
+
+class MemcachedBytecodeCache(BytecodeCache):
+    """This class implements a bytecode cache that uses a memcache cache for
+    storing the information.  It does not enforce a specific memcache library
+    (tummy's memcache or cmemcache) but will accept any class that provides
+    the minimal interface required.
+
+    Libraries compatible with this class:
+
+    -   `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
+    -   `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
+    -   `cmemcache <http://gijsbert.org/cmemcache/>`_
+
+    (Unfortunately the django cache interface is not compatible because it
+    does not support storing binary data, only unicode.  You can however pass
+    the underlying cache client to the bytecode cache which is available
+    as `django.core.cache.cache._client`.)
+
+    The minimal interface for the client passed to the constructor is this:
+
+    .. class:: MinimalClientInterface
+
+        .. method:: set(key, value[, timeout])
+
+            Stores the bytecode in the cache.  `value` is a string and
+            `timeout` the timeout of the key.  If timeout is not provided
+            a default timeout or no timeout should be assumed, if it's
+            provided it's an integer with the number of seconds the cache
+            item should exist.
+
+        .. method:: get(key)
+
+            Returns the value for the cache key.  If the item does not
+            exist in the cache the return value must be `None`.
+
+    The other arguments to the constructor are the prefix for all keys that
+    is added before the actual cache key and the timeout for the bytecode in
+    the cache system.  We recommend a high (or no) timeout.
+
+    This bytecode cache does not support clearing of used items in the cache.
+    The clear method is a no-operation function.
+    """
+
+    def __init__(self, client, prefix='jinja2/bytecode/', timeout=None):
+        self.client = client
+        self.prefix = prefix
+        self.timeout = timeout
+
+    def load_bytecode(self, bucket):
+        code = self.client.get(self.prefix + bucket.key)
+        if code is not None:
+            bucket.bytecode_from_string(code)
+
+    def dump_bytecode(self, bucket):
+        args = (self.prefix + bucket.key, bucket.bytecode_to_string())
+        if self.timeout is not None:
+            args += (self.timeout,)
+        self.client.set(*args)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/compiler.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/compiler.py b/ambari-common/src/main/python/jinja2/jinja2/compiler.py
new file mode 100644
index 0000000..5764159
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/compiler.py
@@ -0,0 +1,1640 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.compiler
+    ~~~~~~~~~~~~~~~
+
+    Compiles nodes into python code.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from cStringIO import StringIO
+from itertools import chain
+from copy import deepcopy
+from jinja2 import nodes
+from jinja2.nodes import EvalContext
+from jinja2.visitor import NodeVisitor, NodeTransformer
+from jinja2.exceptions import TemplateAssertionError
+from jinja2.utils import Markup, concat, escape, is_python_keyword, next
+
+
+operators = {
+    'eq':       '==',
+    'ne':       '!=',
+    'gt':       '>',
+    'gteq':     '>=',
+    'lt':       '<',
+    'lteq':     '<=',
+    'in':       'in',
+    'notin':    'not in'
+}
+
+try:
+    exec '(0 if 0 else 0)'
+except SyntaxError:
+    have_condexpr = False
+else:
+    have_condexpr = True
+
+
+# what method to iterate over items do we want to use for dict iteration
+# in generated code?  on 2.x let's go with iteritems, on 3.x with items
+if hasattr(dict, 'iteritems'):
+    dict_item_iter = 'iteritems'
+else:
+    dict_item_iter = 'items'
+
+
+# does if 0: dummy(x) get us x into the scope?
+def unoptimize_before_dead_code():
+    x = 42
+    def f():
+        if 0: dummy(x)
+    return f
+unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
+
+
+def generate(node, environment, name, filename, stream=None,
+             defer_init=False):
+    """Generate the python source for a node tree."""
+    if not isinstance(node, nodes.Template):
+        raise TypeError('Can\'t compile non template nodes')
+    generator = CodeGenerator(environment, name, filename, stream, defer_init)
+    generator.visit(node)
+    if stream is None:
+        return generator.stream.getvalue()
+
+
+def has_safe_repr(value):
+    """Does the node have a safe representation?"""
+    if value is None or value is NotImplemented or value is Ellipsis:
+        return True
+    if isinstance(value, (bool, int, long, float, complex, basestring,
+                          xrange, Markup)):
+        return True
+    if isinstance(value, (tuple, list, set, frozenset)):
+        for item in value:
+            if not has_safe_repr(item):
+                return False
+        return True
+    elif isinstance(value, dict):
+        for key, value in value.iteritems():
+            if not has_safe_repr(key):
+                return False
+            if not has_safe_repr(value):
+                return False
+        return True
+    return False
+
+
+def find_undeclared(nodes, names):
+    """Check if the names passed are accessed undeclared.  The return value
+    is a set of all the undeclared names from the sequence of names found.
+    """
+    visitor = UndeclaredNameVisitor(names)
+    try:
+        for node in nodes:
+            visitor.visit(node)
+    except VisitorExit:
+        pass
+    return visitor.undeclared
+
+
+class Identifiers(object):
+    """Tracks the status of identifiers in frames."""
+
+    def __init__(self):
+        # variables that are known to be declared (probably from outer
+        # frames or because they are special for the frame)
+        self.declared = set()
+
+        # undeclared variables from outer scopes
+        self.outer_undeclared = set()
+
+        # names that are accessed without being explicitly declared by
+        # this one or any of the outer scopes.  Names can appear both in
+        # declared and undeclared.
+        self.undeclared = set()
+
+        # names that are declared locally
+        self.declared_locally = set()
+
+        # names that are declared by parameters
+        self.declared_parameter = set()
+
+    def add_special(self, name):
+        """Register a special name like `loop`."""
+        self.undeclared.discard(name)
+        self.declared.add(name)
+
+    def is_declared(self, name, local_only=False):
+        """Check if a name is declared in this or an outer scope."""
+        if name in self.declared_locally or name in self.declared_parameter:
+            return True
+        if local_only:
+            return False
+        return name in self.declared
+
+    def copy(self):
+        return deepcopy(self)
+
+
+class Frame(object):
+    """Holds compile time information for us."""
+
+    def __init__(self, eval_ctx, parent=None):
+        self.eval_ctx = eval_ctx
+        self.identifiers = Identifiers()
+
+        # a toplevel frame is the root + soft frames such as if conditions.
+        self.toplevel = False
+
+        # the root frame is basically just the outermost frame, so no if
+        # conditions.  This information is used to optimize inheritance
+        # situations.
+        self.rootlevel = False
+
+        # in some dynamic inheritance situations the compiler needs to add
+        # write tests around output statements.
+        self.require_output_check = parent and parent.require_output_check
+
+        # inside some tags we are using a buffer rather than yield statements.
+        # this for example affects {% filter %} or {% macro %}.  If a frame
+        # is buffered this variable points to the name of the list used as
+        # buffer.
+        self.buffer = None
+
+        # the name of the block we're in, otherwise None.
+        self.block = parent and parent.block or None
+
+        # a set of actually assigned names
+        self.assigned_names = set()
+
+        # the parent of this frame
+        self.parent = parent
+
+        if parent is not None:
+            self.identifiers.declared.update(
+                parent.identifiers.declared |
+                parent.identifiers.declared_parameter |
+                parent.assigned_names
+            )
+            self.identifiers.outer_undeclared.update(
+                parent.identifiers.undeclared -
+                self.identifiers.declared
+            )
+            self.buffer = parent.buffer
+
+    def copy(self):
+        """Create a copy of the current one."""
+        rv = object.__new__(self.__class__)
+        rv.__dict__.update(self.__dict__)
+        rv.identifiers = object.__new__(self.identifiers.__class__)
+        rv.identifiers.__dict__.update(self.identifiers.__dict__)
+        return rv
+
+    def inspect(self, nodes, hard_scope=False):
+        """Walk the node and check for identifiers.  If the scope is hard (eg:
+        enforce on a python level) overrides from outer scopes are tracked
+        differently.
+        """
+        visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
+        for node in nodes:
+            visitor.visit(node)
+
+    def find_shadowed(self, extra=()):
+        """Find all the shadowed names.  extra is an iterable of variables
+        that may be defined with `add_special` which may occour scoped.
+        """
+        i = self.identifiers
+        return (i.declared | i.outer_undeclared) & \
+               (i.declared_locally | i.declared_parameter) | \
+               set(x for x in extra if i.is_declared(x))
+
+    def inner(self):
+        """Return an inner frame."""
+        return Frame(self.eval_ctx, self)
+
+    def soft(self):
+        """Return a soft frame.  A soft frame may not be modified as
+        standalone thing as it shares the resources with the frame it
+        was created of, but it's not a rootlevel frame any longer.
+        """
+        rv = self.copy()
+        rv.rootlevel = False
+        return rv
+
+    __copy__ = copy
+
+
+class VisitorExit(RuntimeError):
+    """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
+
+
+class DependencyFinderVisitor(NodeVisitor):
+    """A visitor that collects filter and test calls."""
+
+    def __init__(self):
+        self.filters = set()
+        self.tests = set()
+
+    def visit_Filter(self, node):
+        self.generic_visit(node)
+        self.filters.add(node.name)
+
+    def visit_Test(self, node):
+        self.generic_visit(node)
+        self.tests.add(node.name)
+
+    def visit_Block(self, node):
+        """Stop visiting at blocks."""
+
+
+class UndeclaredNameVisitor(NodeVisitor):
+    """A visitor that checks if a name is accessed without being
+    declared.  This is different from the frame visitor as it will
+    not stop at closure frames.
+    """
+
+    def __init__(self, names):
+        self.names = set(names)
+        self.undeclared = set()
+
+    def visit_Name(self, node):
+        if node.ctx == 'load' and node.name in self.names:
+            self.undeclared.add(node.name)
+            if self.undeclared == self.names:
+                raise VisitorExit()
+        else:
+            self.names.discard(node.name)
+
+    def visit_Block(self, node):
+        """Stop visiting a blocks."""
+
+
+class FrameIdentifierVisitor(NodeVisitor):
+    """A visitor for `Frame.inspect`."""
+
+    def __init__(self, identifiers, hard_scope):
+        self.identifiers = identifiers
+        self.hard_scope = hard_scope
+
+    def visit_Name(self, node):
+        """All assignments to names go through this function."""
+        if node.ctx == 'store':
+            self.identifiers.declared_locally.add(node.name)
+        elif node.ctx == 'param':
+            self.identifiers.declared_parameter.add(node.name)
+        elif node.ctx == 'load' and not \
+             self.identifiers.is_declared(node.name, self.hard_scope):
+            self.identifiers.undeclared.add(node.name)
+
+    def visit_If(self, node):
+        self.visit(node.test)
+        real_identifiers = self.identifiers
+
+        old_names = real_identifiers.declared_locally | \
+                    real_identifiers.declared_parameter
+
+        def inner_visit(nodes):
+            if not nodes:
+                return set()
+            self.identifiers = real_identifiers.copy()
+            for subnode in nodes:
+                self.visit(subnode)
+            rv = self.identifiers.declared_locally - old_names
+            # we have to remember the undeclared variables of this branch
+            # because we will have to pull them.
+            real_identifiers.undeclared.update(self.identifiers.undeclared)
+            self.identifiers = real_identifiers
+            return rv
+
+        body = inner_visit(node.body)
+        else_ = inner_visit(node.else_ or ())
+
+        # the differences between the two branches are also pulled as
+        # undeclared variables
+        real_identifiers.undeclared.update(body.symmetric_difference(else_) -
+                                           real_identifiers.declared)
+
+        # remember those that are declared.
+        real_identifiers.declared_locally.update(body | else_)
+
+    def visit_Macro(self, node):
+        self.identifiers.declared_locally.add(node.name)
+
+    def visit_Import(self, node):
+        self.generic_visit(node)
+        self.identifiers.declared_locally.add(node.target)
+
+    def visit_FromImport(self, node):
+        self.generic_visit(node)
+        for name in node.names:
+            if isinstance(name, tuple):
+                self.identifiers.declared_locally.add(name[1])
+            else:
+                self.identifiers.declared_locally.add(name)
+
+    def visit_Assign(self, node):
+        """Visit assignments in the correct order."""
+        self.visit(node.node)
+        self.visit(node.target)
+
+    def visit_For(self, node):
+        """Visiting stops at for blocks.  However the block sequence
+        is visited as part of the outer scope.
+        """
+        self.visit(node.iter)
+
+    def visit_CallBlock(self, node):
+        self.visit(node.call)
+
+    def visit_FilterBlock(self, node):
+        self.visit(node.filter)
+
+    def visit_Scope(self, node):
+        """Stop visiting at scopes."""
+
+    def visit_Block(self, node):
+        """Stop visiting at blocks."""
+
+
+class CompilerExit(Exception):
+    """Raised if the compiler encountered a situation where it just
+    doesn't make sense to further process the code.  Any block that
+    raises such an exception is not further processed.
+    """
+
+
+class CodeGenerator(NodeVisitor):
+
+    def __init__(self, environment, name, filename, stream=None,
+                 defer_init=False):
+        if stream is None:
+            stream = StringIO()
+        self.environment = environment
+        self.name = name
+        self.filename = filename
+        self.stream = stream
+        self.created_block_context = False
+        self.defer_init = defer_init
+
+        # aliases for imports
+        self.import_aliases = {}
+
+        # a registry for all blocks.  Because blocks are moved out
+        # into the global python scope they are registered here
+        self.blocks = {}
+
+        # the number of extends statements so far
+        self.extends_so_far = 0
+
+        # some templates have a rootlevel extends.  In this case we
+        # can safely assume that we're a child template and do some
+        # more optimizations.
+        self.has_known_extends = False
+
+        # the current line number
+        self.code_lineno = 1
+
+        # registry of all filters and tests (global, not block local)
+        self.tests = {}
+        self.filters = {}
+
+        # the debug information
+        self.debug_info = []
+        self._write_debug_info = None
+
+        # the number of new lines before the next write()
+        self._new_lines = 0
+
+        # the line number of the last written statement
+        self._last_line = 0
+
+        # true if nothing was written so far.
+        self._first_write = True
+
+        # used by the `temporary_identifier` method to get new
+        # unique, temporary identifier
+        self._last_identifier = 0
+
+        # the current indentation
+        self._indentation = 0
+
+    # -- Various compilation helpers
+
+    def fail(self, msg, lineno):
+        """Fail with a :exc:`TemplateAssertionError`."""
+        raise TemplateAssertionError(msg, lineno, self.name, self.filename)
+
+    def temporary_identifier(self):
+        """Get a new unique identifier."""
+        self._last_identifier += 1
+        return 't_%d' % self._last_identifier
+
+    def buffer(self, frame):
+        """Enable buffering for the frame from that point onwards."""
+        frame.buffer = self.temporary_identifier()
+        self.writeline('%s = []' % frame.buffer)
+
+    def return_buffer_contents(self, frame):
+        """Return the buffer contents of the frame."""
+        if frame.eval_ctx.volatile:
+            self.writeline('if context.eval_ctx.autoescape:')
+            self.indent()
+            self.writeline('return Markup(concat(%s))' % frame.buffer)
+            self.outdent()
+            self.writeline('else:')
+            self.indent()
+            self.writeline('return concat(%s)' % frame.buffer)
+            self.outdent()
+        elif frame.eval_ctx.autoescape:
+            self.writeline('return Markup(concat(%s))' % frame.buffer)
+        else:
+            self.writeline('return concat(%s)' % frame.buffer)
+
+    def indent(self):
+        """Indent by one."""
+        self._indentation += 1
+
+    def outdent(self, step=1):
+        """Outdent by step."""
+        self._indentation -= step
+
+    def start_write(self, frame, node=None):
+        """Yield or write into the frame buffer."""
+        if frame.buffer is None:
+            self.writeline('yield ', node)
+        else:
+            self.writeline('%s.append(' % frame.buffer, node)
+
+    def end_write(self, frame):
+        """End the writing process started by `start_write`."""
+        if frame.buffer is not None:
+            self.write(')')
+
+    def simple_write(self, s, frame, node=None):
+        """Simple shortcut for start_write + write + end_write."""
+        self.start_write(frame, node)
+        self.write(s)
+        self.end_write(frame)
+
+    def blockvisit(self, nodes, frame):
+        """Visit a list of nodes as block in a frame.  If the current frame
+        is no buffer a dummy ``if 0: yield None`` is written automatically
+        unless the force_generator parameter is set to False.
+        """
+        if frame.buffer is None:
+            self.writeline('if 0: yield None')
+        else:
+            self.writeline('pass')
+        try:
+            for node in nodes:
+                self.visit(node, frame)
+        except CompilerExit:
+            pass
+
+    def write(self, x):
+        """Write a string into the output stream."""
+        if self._new_lines:
+            if not self._first_write:
+                self.stream.write('\n' * self._new_lines)
+                self.code_lineno += self._new_lines
+                if self._write_debug_info is not None:
+                    self.debug_info.append((self._write_debug_info,
+                                            self.code_lineno))
+                    self._write_debug_info = None
+            self._first_write = False
+            self.stream.write('    ' * self._indentation)
+            self._new_lines = 0
+        self.stream.write(x)
+
+    def writeline(self, x, node=None, extra=0):
+        """Combination of newline and write."""
+        self.newline(node, extra)
+        self.write(x)
+
+    def newline(self, node=None, extra=0):
+        """Add one or more newlines before the next write."""
+        self._new_lines = max(self._new_lines, 1 + extra)
+        if node is not None and node.lineno != self._last_line:
+            self._write_debug_info = node.lineno
+            self._last_line = node.lineno
+
+    def signature(self, node, frame, extra_kwargs=None):
+        """Writes a function call to the stream for the current node.
+        A leading comma is added automatically.  The extra keyword
+        arguments may not include python keywords otherwise a syntax
+        error could occour.  The extra keyword arguments should be given
+        as python dict.
+        """
+        # if any of the given keyword arguments is a python keyword
+        # we have to make sure that no invalid call is created.
+        kwarg_workaround = False
+        for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
+            if is_python_keyword(kwarg):
+                kwarg_workaround = True
+                break
+
+        for arg in node.args:
+            self.write(', ')
+            self.visit(arg, frame)
+
+        if not kwarg_workaround:
+            for kwarg in node.kwargs:
+                self.write(', ')
+                self.visit(kwarg, frame)
+            if extra_kwargs is not None:
+                for key, value in extra_kwargs.iteritems():
+                    self.write(', %s=%s' % (key, value))
+        if node.dyn_args:
+            self.write(', *')
+            self.visit(node.dyn_args, frame)
+
+        if kwarg_workaround:
+            if node.dyn_kwargs is not None:
+                self.write(', **dict({')
+            else:
+                self.write(', **{')
+            for kwarg in node.kwargs:
+                self.write('%r: ' % kwarg.key)
+                self.visit(kwarg.value, frame)
+                self.write(', ')
+            if extra_kwargs is not None:
+                for key, value in extra_kwargs.iteritems():
+                    self.write('%r: %s, ' % (key, value))
+            if node.dyn_kwargs is not None:
+                self.write('}, **')
+                self.visit(node.dyn_kwargs, frame)
+                self.write(')')
+            else:
+                self.write('}')
+
+        elif node.dyn_kwargs is not None:
+            self.write(', **')
+            self.visit(node.dyn_kwargs, frame)
+
+    def pull_locals(self, frame):
+        """Pull all the references identifiers into the local scope."""
+        for name in frame.identifiers.undeclared:
+            self.writeline('l_%s = context.resolve(%r)' % (name, name))
+
+    def pull_dependencies(self, nodes):
+        """Pull all the dependencies."""
+        visitor = DependencyFinderVisitor()
+        for node in nodes:
+            visitor.visit(node)
+        for dependency in 'filters', 'tests':
+            mapping = getattr(self, dependency)
+            for name in getattr(visitor, dependency):
+                if name not in mapping:
+                    mapping[name] = self.temporary_identifier()
+                self.writeline('%s = environment.%s[%r]' %
+                               (mapping[name], dependency, name))
+
+    def unoptimize_scope(self, frame):
+        """Disable Python optimizations for the frame."""
+        # XXX: this is not that nice but it has no real overhead.  It
+        # mainly works because python finds the locals before dead code
+        # is removed.  If that breaks we have to add a dummy function
+        # that just accepts the arguments and does nothing.
+        if frame.identifiers.declared:
+            self.writeline('%sdummy(%s)' % (
+                unoptimize_before_dead_code and 'if 0: ' or '',
+                ', '.join('l_' + name for name in frame.identifiers.declared)
+            ))
+
+    def push_scope(self, frame, extra_vars=()):
+        """This function returns all the shadowed variables in a dict
+        in the form name: alias and will write the required assignments
+        into the current scope.  No indentation takes place.
+
+        This also predefines locally declared variables from the loop
+        body because under some circumstances it may be the case that
+
+        `extra_vars` is passed to `Frame.find_shadowed`.
+        """
+        aliases = {}
+        for name in frame.find_shadowed(extra_vars):
+            aliases[name] = ident = self.temporary_identifier()
+            self.writeline('%s = l_%s' % (ident, name))
+        to_declare = set()
+        for name in frame.identifiers.declared_locally:
+            if name not in aliases:
+                to_declare.add('l_' + name)
+        if to_declare:
+            self.writeline(' = '.join(to_declare) + ' = missing')
+        return aliases
+
+    def pop_scope(self, aliases, frame):
+        """Restore all aliases and delete unused variables."""
+        for name, alias in aliases.iteritems():
+            self.writeline('l_%s = %s' % (name, alias))
+        to_delete = set()
+        for name in frame.identifiers.declared_locally:
+            if name not in aliases:
+                to_delete.add('l_' + name)
+        if to_delete:
+            # we cannot use the del statement here because enclosed
+            # scopes can trigger a SyntaxError:
+            #   a = 42; b = lambda: a; del a
+            self.writeline(' = '.join(to_delete) + ' = missing')
+
+    def function_scoping(self, node, frame, children=None,
+                         find_special=True):
+        """In Jinja a few statements require the help of anonymous
+        functions.  Those are currently macros and call blocks and in
+        the future also recursive loops.  As there is currently
+        technical limitation that doesn't allow reading and writing a
+        variable in a scope where the initial value is coming from an
+        outer scope, this function tries to fall back with a common
+        error message.  Additionally the frame passed is modified so
+        that the argumetns are collected and callers are looked up.
+
+        This will return the modified frame.
+        """
+        # we have to iterate twice over it, make sure that works
+        if children is None:
+            children = node.iter_child_nodes()
+        children = list(children)
+        func_frame = frame.inner()
+        func_frame.inspect(children, hard_scope=True)
+
+        # variables that are undeclared (accessed before declaration) and
+        # declared locally *and* part of an outside scope raise a template
+        # assertion error. Reason: we can't generate reasonable code from
+        # it without aliasing all the variables.
+        # this could be fixed in Python 3 where we have the nonlocal
+        # keyword or if we switch to bytecode generation
+        overriden_closure_vars = (
+            func_frame.identifiers.undeclared &
+            func_frame.identifiers.declared &
+            (func_frame.identifiers.declared_locally |
+             func_frame.identifiers.declared_parameter)
+        )
+        if overriden_closure_vars:
+            self.fail('It\'s not possible to set and access variables '
+                      'derived from an outer scope! (affects: %s)' %
+                      ', '.join(sorted(overriden_closure_vars)), node.lineno)
+
+        # remove variables from a closure from the frame's undeclared
+        # identifiers.
+        func_frame.identifiers.undeclared -= (
+            func_frame.identifiers.undeclared &
+            func_frame.identifiers.declared
+        )
+
+        # no special variables for this scope, abort early
+        if not find_special:
+            return func_frame
+
+        func_frame.accesses_kwargs = False
+        func_frame.accesses_varargs = False
+        func_frame.accesses_caller = False
+        func_frame.arguments = args = ['l_' + x.name for x in node.args]
+
+        undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
+
+        if 'caller' in undeclared:
+            func_frame.accesses_caller = True
+            func_frame.identifiers.add_special('caller')
+            args.append('l_caller')
+        if 'kwargs' in undeclared:
+            func_frame.accesses_kwargs = True
+            func_frame.identifiers.add_special('kwargs')
+            args.append('l_kwargs')
+        if 'varargs' in undeclared:
+            func_frame.accesses_varargs = True
+            func_frame.identifiers.add_special('varargs')
+            args.append('l_varargs')
+        return func_frame
+
+    def macro_body(self, node, frame, children=None):
+        """Dump the function def of a macro or call block."""
+        frame = self.function_scoping(node, frame, children)
+        # macros are delayed, they never require output checks
+        frame.require_output_check = False
+        args = frame.arguments
+        # XXX: this is an ugly fix for the loop nesting bug
+        # (tests.test_old_bugs.test_loop_call_bug).  This works around
+        # a identifier nesting problem we have in general.  It's just more
+        # likely to happen in loops which is why we work around it.  The
+        # real solution would be "nonlocal" all the identifiers that are
+        # leaking into a new python frame and might be used both unassigned
+        # and assigned.
+        if 'loop' in frame.identifiers.declared:
+            args = args + ['l_loop=l_loop']
+        self.writeline('def macro(%s):' % ', '.join(args), node)
+        self.indent()
+        self.buffer(frame)
+        self.pull_locals(frame)
+        self.blockvisit(node.body, frame)
+        self.return_buffer_contents(frame)
+        self.outdent()
+        return frame
+
+    def macro_def(self, node, frame):
+        """Dump the macro definition for the def created by macro_body."""
+        arg_tuple = ', '.join(repr(x.name) for x in node.args)
+        name = getattr(node, 'name', None)
+        if len(node.args) == 1:
+            arg_tuple += ','
+        self.write('Macro(environment, macro, %r, (%s), (' %
+                   (name, arg_tuple))
+        for arg in node.defaults:
+            self.visit(arg, frame)
+            self.write(', ')
+        self.write('), %r, %r, %r)' % (
+            bool(frame.accesses_kwargs),
+            bool(frame.accesses_varargs),
+            bool(frame.accesses_caller)
+        ))
+
+    def position(self, node):
+        """Return a human readable position for the node."""
+        rv = 'line %d' % node.lineno
+        if self.name is not None:
+            rv += ' in ' + repr(self.name)
+        return rv
+
+    # -- Statement Visitors
+
+    def visit_Template(self, node, frame=None):
+        assert frame is None, 'no root frame allowed'
+        eval_ctx = EvalContext(self.environment, self.name)
+
+        from jinja2.runtime import __all__ as exported
+        self.writeline('from __future__ import division')
+        self.writeline('from jinja2.runtime import ' + ', '.join(exported))
+        if not unoptimize_before_dead_code:
+            self.writeline('dummy = lambda *x: None')
+
+        # if we want a deferred initialization we cannot move the
+        # environment into a local name
+        envenv = not self.defer_init and ', environment=environment' or ''
+
+        # do we have an extends tag at all?  If not, we can save some
+        # overhead by just not processing any inheritance code.
+        have_extends = node.find(nodes.Extends) is not None
+
+        # find all blocks
+        for block in node.find_all(nodes.Block):
+            if block.name in self.blocks:
+                self.fail('block %r defined twice' % block.name, block.lineno)
+            self.blocks[block.name] = block
+
+        # find all imports and import them
+        for import_ in node.find_all(nodes.ImportedName):
+            if import_.importname not in self.import_aliases:
+                imp = import_.importname
+                self.import_aliases[imp] = alias = self.temporary_identifier()
+                if '.' in imp:
+                    module, obj = imp.rsplit('.', 1)
+                    self.writeline('from %s import %s as %s' %
+                                   (module, obj, alias))
+                else:
+                    self.writeline('import %s as %s' % (imp, alias))
+
+        # add the load name
+        self.writeline('name = %r' % self.name)
+
+        # generate the root render function.
+        self.writeline('def root(context%s):' % envenv, extra=1)
+
+        # process the root
+        frame = Frame(eval_ctx)
+        frame.inspect(node.body)
+        frame.toplevel = frame.rootlevel = True
+        frame.require_output_check = have_extends and not self.has_known_extends
+        self.indent()
+        if have_extends:
+            self.writeline('parent_template = None')
+        if 'self' in find_undeclared(node.body, ('self',)):
+            frame.identifiers.add_special('self')
+            self.writeline('l_self = TemplateReference(context)')
+        self.pull_locals(frame)
+        self.pull_dependencies(node.body)
+        self.blockvisit(node.body, frame)
+        self.outdent()
+
+        # make sure that the parent root is called.
+        if have_extends:
+            if not self.has_known_extends:
+                self.indent()
+                self.writeline('if parent_template is not None:')
+            self.indent()
+            self.writeline('for event in parent_template.'
+                           'root_render_func(context):')
+            self.indent()
+            self.writeline('yield event')
+            self.outdent(2 + (not self.has_known_extends))
+
+        # at this point we now have the blocks collected and can visit them too.
+        for name, block in self.blocks.iteritems():
+            block_frame = Frame(eval_ctx)
+            block_frame.inspect(block.body)
+            block_frame.block = name
+            self.writeline('def block_%s(context%s):' % (name, envenv),
+                           block, 1)
+            self.indent()
+            undeclared = find_undeclared(block.body, ('self', 'super'))
+            if 'self' in undeclared:
+                block_frame.identifiers.add_special('self')
+                self.writeline('l_self = TemplateReference(context)')
+            if 'super' in undeclared:
+                block_frame.identifiers.add_special('super')
+                self.writeline('l_super = context.super(%r, '
+                               'block_%s)' % (name, name))
+            self.pull_locals(block_frame)
+            self.pull_dependencies(block.body)
+            self.blockvisit(block.body, block_frame)
+            self.outdent()
+
+        self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
+                                                   for x in self.blocks),
+                       extra=1)
+
+        # add a function that returns the debug info
+        self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
+                                                    in self.debug_info))
+
+    def visit_Block(self, node, frame):
+        """Call a block and register it for the template."""
+        level = 1
+        if frame.toplevel:
+            # if we know that we are a child template, there is no need to
+            # check if we are one
+            if self.has_known_extends:
+                return
+            if self.extends_so_far > 0:
+                self.writeline('if parent_template is None:')
+                self.indent()
+                level += 1
+        context = node.scoped and 'context.derived(locals())' or 'context'
+        self.writeline('for event in context.blocks[%r][0](%s):' % (
+                       node.name, context), node)
+        self.indent()
+        self.simple_write('event', frame)
+        self.outdent(level)
+
+    def visit_Extends(self, node, frame):
+        """Calls the extender."""
+        if not frame.toplevel:
+            self.fail('cannot use extend from a non top-level scope',
+                      node.lineno)
+
+        # if the number of extends statements in general is zero so
+        # far, we don't have to add a check if something extended
+        # the template before this one.
+        if self.extends_so_far > 0:
+
+            # if we have a known extends we just add a template runtime
+            # error into the generated code.  We could catch that at compile
+            # time too, but i welcome it not to confuse users by throwing the
+            # same error at different times just "because we can".
+            if not self.has_known_extends:
+                self.writeline('if parent_template is not None:')
+                self.indent()
+            self.writeline('raise TemplateRuntimeError(%r)' %
+                           'extended multiple times')
+            self.outdent()
+
+            # if we have a known extends already we don't need that code here
+            # as we know that the template execution will end here.
+            if self.has_known_extends:
+                raise CompilerExit()
+
+        self.writeline('parent_template = environment.get_template(', node)
+        self.visit(node.template, frame)
+        self.write(', %r)' % self.name)
+        self.writeline('for name, parent_block in parent_template.'
+                       'blocks.%s():' % dict_item_iter)
+        self.indent()
+        self.writeline('context.blocks.setdefault(name, []).'
+                       'append(parent_block)')
+        self.outdent()
+
+        # if this extends statement was in the root level we can take
+        # advantage of that information and simplify the generated code
+        # in the top level from this point onwards
+        if frame.rootlevel:
+            self.has_known_extends = True
+
+        # and now we have one more
+        self.extends_so_far += 1
+
+    def visit_Include(self, node, frame):
+        """Handles includes."""
+        if node.with_context:
+            self.unoptimize_scope(frame)
+        if node.ignore_missing:
+            self.writeline('try:')
+            self.indent()
+
+        func_name = 'get_or_select_template'
+        if isinstance(node.template, nodes.Const):
+            if isinstance(node.template.value, basestring):
+                func_name = 'get_template'
+            elif isinstance(node.template.value, (tuple, list)):
+                func_name = 'select_template'
+        elif isinstance(node.template, (nodes.Tuple, nodes.List)):
+            func_name = 'select_template'
+
+        self.writeline('template = environment.%s(' % func_name, node)
+        self.visit(node.template, frame)
+        self.write(', %r)' % self.name)
+        if node.ignore_missing:
+            self.outdent()
+            self.writeline('except TemplateNotFound:')
+            self.indent()
+            self.writeline('pass')
+            self.outdent()
+            self.writeline('else:')
+            self.indent()
+
+        if node.with_context:
+            self.writeline('for event in template.root_render_func('
+                           'template.new_context(context.parent, True, '
+                           'locals())):')
+        else:
+            self.writeline('for event in template.module._body_stream:')
+
+        self.indent()
+        self.simple_write('event', frame)
+        self.outdent()
+
+        if node.ignore_missing:
+            self.outdent()
+
+    def visit_Import(self, node, frame):
+        """Visit regular imports."""
+        if node.with_context:
+            self.unoptimize_scope(frame)
+        self.writeline('l_%s = ' % node.target, node)
+        if frame.toplevel:
+            self.write('context.vars[%r] = ' % node.target)
+        self.write('environment.get_template(')
+        self.visit(node.template, frame)
+        self.write(', %r).' % self.name)
+        if node.with_context:
+            self.write('make_module(context.parent, True, locals())')
+        else:
+            self.write('module')
+        if frame.toplevel and not node.target.startswith('_'):
+            self.writeline('context.exported_vars.discard(%r)' % node.target)
+        frame.assigned_names.add(node.target)
+
+    def visit_FromImport(self, node, frame):
+        """Visit named imports."""
+        self.newline(node)
+        self.write('included_template = environment.get_template(')
+        self.visit(node.template, frame)
+        self.write(', %r).' % self.name)
+        if node.with_context:
+            self.write('make_module(context.parent, True)')
+        else:
+            self.write('module')
+
+        var_names = []
+        discarded_names = []
+        for name in node.names:
+            if isinstance(name, tuple):
+                name, alias = name
+            else:
+                alias = name
+            self.writeline('l_%s = getattr(included_template, '
+                           '%r, missing)' % (alias, name))
+            self.writeline('if l_%s is missing:' % alias)
+            self.indent()
+            self.writeline('l_%s = environment.undefined(%r %% '
+                           'included_template.__name__, '
+                           'name=%r)' %
+                           (alias, 'the template %%r (imported on %s) does '
+                           'not export the requested name %s' % (
+                                self.position(node),
+                                repr(name)
+                           ), name))
+            self.outdent()
+            if frame.toplevel:
+                var_names.append(alias)
+                if not alias.startswith('_'):
+                    discarded_names.append(alias)
+            frame.assigned_names.add(alias)
+
+        if var_names:
+            if len(var_names) == 1:
+                name = var_names[0]
+                self.writeline('context.vars[%r] = l_%s' % (name, name))
+            else:
+                self.writeline('context.vars.update({%s})' % ', '.join(
+                    '%r: l_%s' % (name, name) for name in var_names
+                ))
+        if discarded_names:
+            if len(discarded_names) == 1:
+                self.writeline('context.exported_vars.discard(%r)' %
+                               discarded_names[0])
+            else:
+                self.writeline('context.exported_vars.difference_'
+                               'update((%s))' % ', '.join(map(repr, discarded_names)))
+
+    def visit_For(self, node, frame):
+        # when calculating the nodes for the inner frame we have to exclude
+        # the iterator contents from it
+        children = node.iter_child_nodes(exclude=('iter',))
+        if node.recursive:
+            loop_frame = self.function_scoping(node, frame, children,
+                                               find_special=False)
+        else:
+            loop_frame = frame.inner()
+            loop_frame.inspect(children)
+
+        # try to figure out if we have an extended loop.  An extended loop
+        # is necessary if the loop is in recursive mode if the special loop
+        # variable is accessed in the body.
+        extended_loop = node.recursive or 'loop' in \
+                        find_undeclared(node.iter_child_nodes(
+                            only=('body',)), ('loop',))
+
+        # if we don't have an recursive loop we have to find the shadowed
+        # variables at that point.  Because loops can be nested but the loop
+        # variable is a special one we have to enforce aliasing for it.
+        if not node.recursive:
+            aliases = self.push_scope(loop_frame, ('loop',))
+
+        # otherwise we set up a buffer and add a function def
+        else:
+            self.writeline('def loop(reciter, loop_render_func):', node)
+            self.indent()
+            self.buffer(loop_frame)
+            aliases = {}
+
+        # make sure the loop variable is a special one and raise a template
+        # assertion error if a loop tries to write to loop
+        if extended_loop:
+            loop_frame.identifiers.add_special('loop')
+        for name in node.find_all(nodes.Name):
+            if name.ctx == 'store' and name.name == 'loop':
+                self.fail('Can\'t assign to special loop variable '
+                          'in for-loop target', name.lineno)
+
+        self.pull_locals(loop_frame)
+        if node.else_:
+            iteration_indicator = self.temporary_identifier()
+            self.writeline('%s = 1' % iteration_indicator)
+
+        # Create a fake parent loop if the else or test section of a
+        # loop is accessing the special loop variable and no parent loop
+        # exists.
+        if 'loop' not in aliases and 'loop' in find_undeclared(
+           node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
+            self.writeline("l_loop = environment.undefined(%r, name='loop')" %
+                ("'loop' is undefined. the filter section of a loop as well "
+                 "as the else block doesn't have access to the special 'loop'"
+                 " variable of the current loop.  Because there is no parent "
+                 "loop it's undefined.  Happened in loop on %s" %
+                 self.position(node)))
+
+        self.writeline('for ', node)
+        self.visit(node.target, loop_frame)
+        self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
+
+        # if we have an extened loop and a node test, we filter in the
+        # "outer frame".
+        if extended_loop and node.test is not None:
+            self.write('(')
+            self.visit(node.target, loop_frame)
+            self.write(' for ')
+            self.visit(node.target, loop_frame)
+            self.write(' in ')
+            if node.recursive:
+                self.write('reciter')
+            else:
+                self.visit(node.iter, loop_frame)
+            self.write(' if (')
+            test_frame = loop_frame.copy()
+            self.visit(node.test, test_frame)
+            self.write('))')
+
+        elif node.recursive:
+            self.write('reciter')
+        else:
+            self.visit(node.iter, loop_frame)
+
+        if node.recursive:
+            self.write(', recurse=loop_render_func):')
+        else:
+            self.write(extended_loop and '):' or ':')
+
+        # tests in not extended loops become a continue
+        if not extended_loop and node.test is not None:
+            self.indent()
+            self.writeline('if not ')
+            self.visit(node.test, loop_frame)
+            self.write(':')
+            self.indent()
+            self.writeline('continue')
+            self.outdent(2)
+
+        self.indent()
+        self.blockvisit(node.body, loop_frame)
+        if node.else_:
+            self.writeline('%s = 0' % iteration_indicator)
+        self.outdent()
+
+        if node.else_:
+            self.writeline('if %s:' % iteration_indicator)
+            self.indent()
+            self.blockvisit(node.else_, loop_frame)
+            self.outdent()
+
+        # reset the aliases if there are any.
+        if not node.recursive:
+            self.pop_scope(aliases, loop_frame)
+
+        # if the node was recursive we have to return the buffer contents
+        # and start the iteration code
+        if node.recursive:
+            self.return_buffer_contents(loop_frame)
+            self.outdent()
+            self.start_write(frame, node)
+            self.write('loop(')
+            self.visit(node.iter, frame)
+            self.write(', loop)')
+            self.end_write(frame)
+
+    def visit_If(self, node, frame):
+        if_frame = frame.soft()
+        self.writeline('if ', node)
+        self.visit(node.test, if_frame)
+        self.write(':')
+        self.indent()
+        self.blockvisit(node.body, if_frame)
+        self.outdent()
+        if node.else_:
+            self.writeline('else:')
+            self.indent()
+            self.blockvisit(node.else_, if_frame)
+            self.outdent()
+
+    def visit_Macro(self, node, frame):
+        macro_frame = self.macro_body(node, frame)
+        self.newline()
+        if frame.toplevel:
+            if not node.name.startswith('_'):
+                self.write('context.exported_vars.add(%r)' % node.name)
+            self.writeline('context.vars[%r] = ' % node.name)
+        self.write('l_%s = ' % node.name)
+        self.macro_def(node, macro_frame)
+        frame.assigned_names.add(node.name)
+
+    def visit_CallBlock(self, node, frame):
+        children = node.iter_child_nodes(exclude=('call',))
+        call_frame = self.macro_body(node, frame, children)
+        self.writeline('caller = ')
+        self.macro_def(node, call_frame)
+        self.start_write(frame, node)
+        self.visit_Call(node.call, call_frame, forward_caller=True)
+        self.end_write(frame)
+
+    def visit_FilterBlock(self, node, frame):
+        filter_frame = frame.inner()
+        filter_frame.inspect(node.iter_child_nodes())
+        aliases = self.push_scope(filter_frame)
+        self.pull_locals(filter_frame)
+        self.buffer(filter_frame)
+        self.blockvisit(node.body, filter_frame)
+        self.start_write(frame, node)
+        self.visit_Filter(node.filter, filter_frame)
+        self.end_write(frame)
+        self.pop_scope(aliases, filter_frame)
+
+    def visit_ExprStmt(self, node, frame):
+        self.newline(node)
+        self.visit(node.node, frame)
+
+    def visit_Output(self, node, frame):
+        # if we have a known extends statement, we don't output anything
+        # if we are in a require_output_check section
+        if self.has_known_extends and frame.require_output_check:
+            return
+
+        if self.environment.finalize:
+            finalize = lambda x: unicode(self.environment.finalize(x))
+        else:
+            finalize = unicode
+
+        # if we are inside a frame that requires output checking, we do so
+        outdent_later = False
+        if frame.require_output_check:
+            self.writeline('if parent_template is None:')
+            self.indent()
+            outdent_later = True
+
+        # try to evaluate as many chunks as possible into a static
+        # string at compile time.
+        body = []
+        for child in node.nodes:
+            try:
+                const = child.as_const(frame.eval_ctx)
+            except nodes.Impossible:
+                body.append(child)
+                continue
+            # the frame can't be volatile here, becaus otherwise the
+            # as_const() function would raise an Impossible exception
+            # at that point.
+            try:
+                if frame.eval_ctx.autoescape:
+                    if hasattr(const, '__html__'):
+                        const = const.__html__()
+                    else:
+                        const = escape(const)
+                const = finalize(const)
+            except:
+                # if something goes wrong here we evaluate the node
+                # at runtime for easier debugging
+                body.append(child)
+                continue
+            if body and isinstance(body[-1], list):
+                body[-1].append(const)
+            else:
+                body.append([const])
+
+        # if we have less than 3 nodes or a buffer we yield or extend/append
+        if len(body) < 3 or frame.buffer is not None:
+            if frame.buffer is not None:
+                # for one item we append, for more we extend
+                if len(body) == 1:
+                    self.writeline('%s.append(' % frame.buffer)
+                else:
+                    self.writeline('%s.extend((' % frame.buffer)
+                self.indent()
+            for item in body:
+                if isinstance(item, list):
+                    val = repr(concat(item))
+                    if frame.buffer is None:
+                        self.writeline('yield ' + val)
+                    else:
+                        self.writeline(val + ', ')
+                else:
+                    if frame.buffer is None:
+                        self.writeline('yield ', item)
+                    else:
+                        self.newline(item)
+                    close = 1
+                    if frame.eval_ctx.volatile:
+                        self.write('(context.eval_ctx.autoescape and'
+                                   ' escape or to_string)(')
+                    elif frame.eval_ctx.autoescape:
+                        self.write('escape(')
+                    else:
+                        self.write('to_string(')
+                    if self.environment.finalize is not None:
+                        self.write('environment.finalize(')
+                        close += 1
+                    self.visit(item, frame)
+                    self.write(')' * close)
+                    if frame.buffer is not None:
+                        self.write(', ')
+            if frame.buffer is not None:
+                # close the open parentheses
+                self.outdent()
+                self.writeline(len(body) == 1 and ')' or '))')
+
+        # otherwise we create a format string as this is faster in that case
+        else:
+            format = []
+            arguments = []
+            for item in body:
+                if isinstance(item, list):
+                    format.append(concat(item).replace('%', '%%'))
+                else:
+                    format.append('%s')
+                    arguments.append(item)
+            self.writeline('yield ')
+            self.write(repr(concat(format)) + ' % (')
+            idx = -1
+            self.indent()
+            for argument in arguments:
+                self.newline(argument)
+                close = 0
+                if frame.eval_ctx.volatile:
+                    self.write('(context.eval_ctx.autoescape and'
+                               ' escape or to_string)(')
+                    close += 1
+                elif frame.eval_ctx.autoescape:
+                    self.write('escape(')
+                    close += 1
+                if self.environment.finalize is not None:
+                    self.write('environment.finalize(')
+                    close += 1
+                self.visit(argument, frame)
+                self.write(')' * close + ', ')
+            self.outdent()
+            self.writeline(')')
+
+        if outdent_later:
+            self.outdent()
+
+    def visit_Assign(self, node, frame):
+        self.newline(node)
+        # toplevel assignments however go into the local namespace and
+        # the current template's context.  We create a copy of the frame
+        # here and add a set so that the Name visitor can add the assigned
+        # names here.
+        if frame.toplevel:
+            assignment_frame = frame.copy()
+            assignment_frame.toplevel_assignments = set()
+        else:
+            assignment_frame = frame
+        self.visit(node.target, assignment_frame)
+        self.write(' = ')
+        self.visit(node.node, frame)
+
+        # make sure toplevel assignments are added to the context.
+        if frame.toplevel:
+            public_names = [x for x in assignment_frame.toplevel_assignments
+                            if not x.startswith('_')]
+            if len(assignment_frame.toplevel_assignments) == 1:
+                name = next(iter(assignment_frame.toplevel_assignments))
+                self.writeline('context.vars[%r] = l_%s' % (name, name))
+            else:
+                self.writeline('context.vars.update({')
+                for idx, name in enumerate(assignment_frame.toplevel_assignments):
+                    if idx:
+                        self.write(', ')
+                    self.write('%r: l_%s' % (name, name))
+                self.write('})')
+            if public_names:
+                if len(public_names) == 1:
+                    self.writeline('context.exported_vars.add(%r)' %
+                                   public_names[0])
+                else:
+                    self.writeline('context.exported_vars.update((%s))' %
+                                   ', '.join(map(repr, public_names)))
+
+    # -- Expression Visitors
+
+    def visit_Name(self, node, frame):
+        if node.ctx == 'store' and frame.toplevel:
+            frame.toplevel_assignments.add(node.name)
+        self.write('l_' + node.name)
+        frame.assigned_names.add(node.name)
+
+    def visit_Const(self, node, frame):
+        val = node.value
+        if isinstance(val, float):
+            self.write(str(val))
+        else:
+            self.write(repr(val))
+
+    def visit_TemplateData(self, node, frame):
+        try:
+            self.write(repr(node.as_const(frame.eval_ctx)))
+        except nodes.Impossible:
+            self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
+                       % node.data)
+
+    def visit_Tuple(self, node, frame):
+        self.write('(')
+        idx = -1
+        for idx, item in enumerate(node.items):
+            if idx:
+                self.write(', ')
+            self.visit(item, frame)
+        self.write(idx == 0 and ',)' or ')')
+
+    def visit_List(self, node, frame):
+        self.write('[')
+        for idx, item in enumerate(node.items):
+            if idx:
+                self.write(', ')
+            self.visit(item, frame)
+        self.write(']')
+
+    def visit_Dict(self, node, frame):
+        self.write('{')
+        for idx, item in enumerate(node.items):
+            if idx:
+                self.write(', ')
+            self.visit(item.key, frame)
+            self.write(': ')
+            self.visit(item.value, frame)
+        self.write('}')
+
+    def binop(operator):
+        def visitor(self, node, frame):
+            self.write('(')
+            self.visit(node.left, frame)
+            self.write(' %s ' % operator)
+            self.visit(node.right, frame)
+            self.write(')')
+        return visitor
+
+    def uaop(operator):
+        def visitor(self, node, frame):
+            self.write('(' + operator)
+            self.visit(node.node, frame)
+            self.write(')')
+        return visitor
+
+    visit_Add = binop('+')
+    visit_Sub = binop('-')
+    visit_Mul = binop('*')
+    visit_Div = binop('/')
+    visit_FloorDiv = binop('//')
+    visit_Pow = binop('**')
+    visit_Mod = binop('%')
+    visit_And = binop('and')
+    visit_Or = binop('or')
+    visit_Pos = uaop('+')
+    visit_Neg = uaop('-')
+    visit_Not = uaop('not ')
+    del binop, uaop
+
+    def visit_Concat(self, node, frame):
+        if frame.eval_ctx.volatile:
+            func_name = '(context.eval_ctx.volatile and' \
+                        ' markup_join or unicode_join)'
+        elif frame.eval_ctx.autoescape:
+            func_name = 'markup_join'
+        else:
+            func_name = 'unicode_join'
+        self.write('%s((' % func_name)
+        for arg in node.nodes:
+            self.visit(arg, frame)
+            self.write(', ')
+        self.write('))')
+
+    def visit_Compare(self, node, frame):
+        self.visit(node.expr, frame)
+        for op in node.ops:
+            self.visit(op, frame)
+
+    def visit_Operand(self, node, frame):
+        self.write(' %s ' % operators[node.op])
+        self.visit(node.expr, frame)
+
+    def visit_Getattr(self, node, frame):
+        self.write('environment.getattr(')
+        self.visit(node.node, frame)
+        self.write(', %r)' % node.attr)
+
+    def visit_Getitem(self, node, frame):
+        # slices bypass the environment getitem method.
+        if isinstance(node.arg, nodes.Slice):
+            self.visit(node.node, frame)
+            self.write('[')
+            self.visit(node.arg, frame)
+            self.write(']')
+        else:
+            self.write('environment.getitem(')
+            self.visit(node.node, frame)
+            self.write(', ')
+            self.visit(node.arg, frame)
+            self.write(')')
+
+    def visit_Slice(self, node, frame):
+        if node.start is not None:
+            self.visit(node.start, frame)
+        self.write(':')
+        if node.stop is not None:
+            self.visit(node.stop, frame)
+        if node.step is not None:
+            self.write(':')
+            self.visit(node.step, frame)
+
+    def visit_Filter(self, node, frame):
+        self.write(self.filters[node.name] + '(')
+        func = self.environment.filters.get(node.name)
+        if func is None:
+            self.fail('no filter named %r' % node.name, node.lineno)
+        if getattr(func, 'contextfilter', False):
+            self.write('context, ')
+        elif getattr(func, 'evalcontextfilter', False):
+            self.write('context.eval_ctx, ')
+        elif getattr(func, 'environmentfilter', False):
+            self.write('environment, ')
+
+        # if the filter node is None we are inside a filter block
+        # and want to write to the current buffer
+        if node.node is not None:
+            self.visit(node.node, frame)
+        elif frame.eval_ctx.volatile:
+            self.write('(context.eval_ctx.autoescape and'
+                       ' Markup(concat(%s)) or concat(%s))' %
+                       (frame.buffer, frame.buffer))
+        elif frame.eval_ctx.autoescape:
+            self.write('Markup(concat(%s))' % frame.buffer)
+        else:
+            self.write('concat(%s)' % frame.buffer)
+        self.signature(node, frame)
+        self.write(')')
+
+    def visit_Test(self, node, frame):
+        self.write(self.tests[node.name] + '(')
+        if node.name not in self.environment.tests:
+            self.fail('no test named %r' % node.name, node.lineno)
+        self.visit(node.node, frame)
+        self.signature(node, frame)
+        self.write(')')
+
+    def visit_CondExpr(self, node, frame):
+        def write_expr2():
+            if node.expr2 is not None:
+                return self.visit(node.expr2, frame)
+            self.write('environment.undefined(%r)' % ('the inline if-'
+                       'expression on %s evaluated to false and '
+                       'no else section was defined.' % self.position(node)))
+
+        if not have_condexpr:
+            self.write('((')
+            self.visit(node.test, frame)
+            self.write(') and (')
+            self.visit(node.expr1, frame)
+            self.write(',) or (')
+            write_expr2()
+            self.write(',))[0]')
+        else:
+            self.write('(')
+            self.visit(node.expr1, frame)
+            self.write(' if ')
+            self.visit(node.test, frame)
+            self.write(' else ')
+            write_expr2()
+            self.write(')')
+
+    def visit_Call(self, node, frame, forward_caller=False):
+        if self.environment.sandboxed:
+            self.write('environment.call(context, ')
+        else:
+            self.write('context.call(')
+        self.visit(node.node, frame)
+        extra_kwargs = forward_caller and {'caller': 'caller'} or None
+        self.signature(node, frame, extra_kwargs)
+        self.write(')')
+
+    def visit_Keyword(self, node, frame):
+        self.write(node.key + '=')
+        self.visit(node.value, frame)
+
+    # -- Unused nodes for extensions
+
+    def visit_MarkSafe(self, node, frame):
+        self.write('Markup(')
+        self.visit(node.expr, frame)
+        self.write(')')
+
+    def visit_MarkSafeIfAutoescape(self, node, frame):
+        self.write('(context.eval_ctx.autoescape and Markup or identity)(')
+        self.visit(node.expr, frame)
+        self.write(')')
+
+    def visit_EnvironmentAttribute(self, node, frame):
+        self.write('environment.' + node.name)
+
+    def visit_ExtensionAttribute(self, node, frame):
+        self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
+
+    def visit_ImportedName(self, node, frame):
+        self.write(self.import_aliases[node.importname])
+
+    def visit_InternalName(self, node, frame):
+        self.write(node.name)
+
+    def visit_ContextReference(self, node, frame):
+        self.write('context')
+
+    def visit_Continue(self, node, frame):
+        self.writeline('continue', node)
+
+    def visit_Break(self, node, frame):
+        self.writeline('break', node)
+
+    def visit_Scope(self, node, frame):
+        scope_frame = frame.inner()
+        scope_frame.inspect(node.iter_child_nodes())
+        aliases = self.push_scope(scope_frame)
+        self.pull_locals(scope_frame)
+        self.blockvisit(node.body, scope_frame)
+        self.pop_scope(aliases, scope_frame)
+
+    def visit_EvalContextModifier(self, node, frame):
+        for keyword in node.options:
+            self.writeline('context.eval_ctx.%s = ' % keyword.key)
+            self.visit(keyword.value, frame)
+            try:
+                val = keyword.value.as_const(frame.eval_ctx)
+            except nodes.Impossible:
+                frame.eval_ctx.volatile = True
+            else:
+                setattr(frame.eval_ctx, keyword.key, val)
+
+    def visit_ScopedEvalContextModifier(self, node, frame):
+        old_ctx_name = self.temporary_identifier()
+        safed_ctx = frame.eval_ctx.save()
+        self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
+        self.visit_EvalContextModifier(node, frame)
+        for child in node.body:
+            self.visit(child, frame)
+        frame.eval_ctx.revert(safed_ctx)
+        self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/constants.py b/ambari-common/src/main/python/jinja2/jinja2/constants.py
new file mode 100644
index 0000000..cab203c
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/constants.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja.constants
+    ~~~~~~~~~~~~~~~
+
+    Various constants.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+
+
+#: list of lorem ipsum words used by the lipsum() helper function
+LOREM_IPSUM_WORDS = u'''\
+a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
+auctor augue bibendum blandit class commodo condimentum congue consectetuer
+consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
+diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
+elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
+faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
+hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
+justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
+luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
+mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
+nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
+penatibus per pharetra phasellus placerat platea porta porttitor posuere
+potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
+ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
+sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
+tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
+ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
+viverra volutpat vulputate'''

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/debug.py b/ambari-common/src/main/python/jinja2/jinja2/debug.py
new file mode 100644
index 0000000..eb15456
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/debug.py
@@ -0,0 +1,308 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.debug
+    ~~~~~~~~~~~~
+
+    Implements the debug interface for Jinja.  This module does some pretty
+    ugly stuff with the Python traceback system in order to achieve tracebacks
+    with correct line numbers, locals and contents.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import sys
+import traceback
+from jinja2.utils import CodeType, missing, internal_code
+from jinja2.exceptions import TemplateSyntaxError
+
+
+# how does the raise helper look like?
+try:
+    exec "raise TypeError, 'foo'"
+except SyntaxError:
+    raise_helper = 'raise __jinja_exception__[1]'
+except TypeError:
+    raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]'
+
+
+class TracebackFrameProxy(object):
+    """Proxies a traceback frame."""
+
+    def __init__(self, tb):
+        self.tb = tb
+
+    def _set_tb_next(self, next):
+        if tb_set_next is not None:
+            tb_set_next(self.tb, next and next.tb or None)
+        self._tb_next = next
+
+    def _get_tb_next(self):
+        return self._tb_next
+
+    tb_next = property(_get_tb_next, _set_tb_next)
+    del _get_tb_next, _set_tb_next
+
+    @property
+    def is_jinja_frame(self):
+        return '__jinja_template__' in self.tb.tb_frame.f_globals
+
+    def __getattr__(self, name):
+        return getattr(self.tb, name)
+
+
+class ProcessedTraceback(object):
+    """Holds a Jinja preprocessed traceback for priting or reraising."""
+
+    def __init__(self, exc_type, exc_value, frames):
+        assert frames, 'no frames for this traceback?'
+        self.exc_type = exc_type
+        self.exc_value = exc_value
+        self.frames = frames
+
+    def chain_frames(self):
+        """Chains the frames.  Requires ctypes or the debugsupport extension."""
+        prev_tb = None
+        for tb in self.frames:
+            if prev_tb is not None:
+                prev_tb.tb_next = tb
+            prev_tb = tb
+        prev_tb.tb_next = None
+
+    def render_as_text(self, limit=None):
+        """Return a string with the traceback."""
+        lines = traceback.format_exception(self.exc_type, self.exc_value,
+                                           self.frames[0], limit=limit)
+        return ''.join(lines).rstrip()
+
+    def render_as_html(self, full=False):
+        """Return a unicode string with the traceback as rendered HTML."""
+        from jinja2.debugrenderer import render_traceback
+        return u'%s\n\n<!--\n%s\n-->' % (
+            render_traceback(self, full=full),
+            self.render_as_text().decode('utf-8', 'replace')
+        )
+
+    @property
+    def is_template_syntax_error(self):
+        """`True` if this is a template syntax error."""
+        return isinstance(self.exc_value, TemplateSyntaxError)
+
+    @property
+    def exc_info(self):
+        """Exception info tuple with a proxy around the frame objects."""
+        return self.exc_type, self.exc_value, self.frames[0]
+
+    @property
+    def standard_exc_info(self):
+        """Standard python exc_info for re-raising"""
+        return self.exc_type, self.exc_value, self.frames[0].tb
+
+
+def make_traceback(exc_info, source_hint=None):
+    """Creates a processed traceback object from the exc_info."""
+    exc_type, exc_value, tb = exc_info
+    if isinstance(exc_value, TemplateSyntaxError):
+        exc_info = translate_syntax_error(exc_value, source_hint)
+        initial_skip = 0
+    else:
+        initial_skip = 1
+    return translate_exception(exc_info, initial_skip)
+
+
+def translate_syntax_error(error, source=None):
+    """Rewrites a syntax error to please traceback systems."""
+    error.source = source
+    error.translated = True
+    exc_info = (error.__class__, error, None)
+    filename = error.filename
+    if filename is None:
+        filename = '<unknown>'
+    return fake_exc_info(exc_info, filename, error.lineno)
+
+
+def translate_exception(exc_info, initial_skip=0):
+    """If passed an exc_info it will automatically rewrite the exceptions
+    all the way down to the correct line numbers and frames.
+    """
+    tb = exc_info[2]
+    frames = []
+
+    # skip some internal frames if wanted
+    for x in xrange(initial_skip):
+        if tb is not None:
+            tb = tb.tb_next
+    initial_tb = tb
+
+    while tb is not None:
+        # skip frames decorated with @internalcode.  These are internal
+        # calls we can't avoid and that are useless in template debugging
+        # output.
+        if tb.tb_frame.f_code in internal_code:
+            tb = tb.tb_next
+            continue
+
+        # save a reference to the next frame if we override the current
+        # one with a faked one.
+        next = tb.tb_next
+
+        # fake template exceptions
+        template = tb.tb_frame.f_globals.get('__jinja_template__')
+        if template is not None:
+            lineno = template.get_corresponding_lineno(tb.tb_lineno)
+            tb = fake_exc_info(exc_info[:2] + (tb,), template.filename,
+                               lineno)[2]
+
+        frames.append(TracebackFrameProxy(tb))
+        tb = next
+
+    # if we don't have any exceptions in the frames left, we have to
+    # reraise it unchanged.
+    # XXX: can we backup here?  when could this happen?
+    if not frames:
+        raise exc_info[0], exc_info[1], exc_info[2]
+
+    traceback = ProcessedTraceback(exc_info[0], exc_info[1], frames)
+    if tb_set_next is not None:
+        traceback.chain_frames()
+    return traceback
+
+
+def fake_exc_info(exc_info, filename, lineno):
+    """Helper for `translate_exception`."""
+    exc_type, exc_value, tb = exc_info
+
+    # figure the real context out
+    if tb is not None:
+        real_locals = tb.tb_frame.f_locals.copy()
+        ctx = real_locals.get('context')
+        if ctx:
+            locals = ctx.get_all()
+        else:
+            locals = {}
+        for name, value in real_locals.iteritems():
+            if name.startswith('l_') and value is not missing:
+                locals[name[2:]] = value
+
+        # if there is a local called __jinja_exception__, we get
+        # rid of it to not break the debug functionality.
+        locals.pop('__jinja_exception__', None)
+    else:
+        locals = {}
+
+    # assamble fake globals we need
+    globals = {
+        '__name__':             filename,
+        '__file__':             filename,
+        '__jinja_exception__':  exc_info[:2],
+
+        # we don't want to keep the reference to the template around
+        # to not cause circular dependencies, but we mark it as Jinja
+        # frame for the ProcessedTraceback
+        '__jinja_template__':   None
+    }
+
+    # and fake the exception
+    code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec')
+
+    # if it's possible, change the name of the code.  This won't work
+    # on some python environments such as google appengine
+    try:
+        if tb is None:
+            location = 'template'
+        else:
+            function = tb.tb_frame.f_code.co_name
+            if function == 'root':
+                location = 'top-level template code'
+            elif function.startswith('block_'):
+                location = 'block "%s"' % function[6:]
+            else:
+                location = 'template'
+        code = CodeType(0, code.co_nlocals, code.co_stacksize,
+                        code.co_flags, code.co_code, code.co_consts,
+                        code.co_names, code.co_varnames, filename,
+                        location, code.co_firstlineno,
+                        code.co_lnotab, (), ())
+    except:
+        pass
+
+    # execute the code and catch the new traceback
+    try:
+        exec code in globals, locals
+    except:
+        exc_info = sys.exc_info()
+        new_tb = exc_info[2].tb_next
+
+    # return without this frame
+    return exc_info[:2] + (new_tb,)
+
+
+def _init_ugly_crap():
+    """This function implements a few ugly things so that we can patch the
+    traceback objects.  The function returned allows resetting `tb_next` on
+    any python traceback object.
+    """
+    import ctypes
+    from types import TracebackType
+
+    # figure out side of _Py_ssize_t
+    if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
+        _Py_ssize_t = ctypes.c_int64
+    else:
+        _Py_ssize_t = ctypes.c_int
+
+    # regular python
+    class _PyObject(ctypes.Structure):
+        pass
+    _PyObject._fields_ = [
+        ('ob_refcnt', _Py_ssize_t),
+        ('ob_type', ctypes.POINTER(_PyObject))
+    ]
+
+    # python with trace
+    if hasattr(sys, 'getobjects'):
+        class _PyObject(ctypes.Structure):
+            pass
+        _PyObject._fields_ = [
+            ('_ob_next', ctypes.POINTER(_PyObject)),
+            ('_ob_prev', ctypes.POINTER(_PyObject)),
+            ('ob_refcnt', _Py_ssize_t),
+            ('ob_type', ctypes.POINTER(_PyObject))
+        ]
+
+    class _Traceback(_PyObject):
+        pass
+    _Traceback._fields_ = [
+        ('tb_next', ctypes.POINTER(_Traceback)),
+        ('tb_frame', ctypes.POINTER(_PyObject)),
+        ('tb_lasti', ctypes.c_int),
+        ('tb_lineno', ctypes.c_int)
+    ]
+
+    def tb_set_next(tb, next):
+        """Set the tb_next attribute of a traceback object."""
+        if not (isinstance(tb, TracebackType) and
+                (next is None or isinstance(next, TracebackType))):
+            raise TypeError('tb_set_next arguments must be traceback objects')
+        obj = _Traceback.from_address(id(tb))
+        if tb.tb_next is not None:
+            old = _Traceback.from_address(id(tb.tb_next))
+            old.ob_refcnt -= 1
+        if next is None:
+            obj.tb_next = ctypes.POINTER(_Traceback)()
+        else:
+            next = _Traceback.from_address(id(next))
+            next.ob_refcnt += 1
+            obj.tb_next = ctypes.pointer(next)
+
+    return tb_set_next
+
+
+# try to get a tb_set_next implementation
+try:
+    from jinja2._debugsupport import tb_set_next
+except ImportError:
+    try:
+        tb_set_next = _init_ugly_crap()
+    except:
+        tb_set_next = None
+del _init_ugly_crap

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/defaults.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/defaults.py b/ambari-common/src/main/python/jinja2/jinja2/defaults.py
new file mode 100644
index 0000000..d2d4544
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/defaults.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.defaults
+    ~~~~~~~~~~~~~~~
+
+    Jinja default filters and tags.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
+
+
+# defaults for the parser / lexer
+BLOCK_START_STRING = '{%'
+BLOCK_END_STRING = '%}'
+VARIABLE_START_STRING = '{{'
+VARIABLE_END_STRING = '}}'
+COMMENT_START_STRING = '{#'
+COMMENT_END_STRING = '#}'
+LINE_STATEMENT_PREFIX = None
+LINE_COMMENT_PREFIX = None
+TRIM_BLOCKS = False
+NEWLINE_SEQUENCE = '\n'
+
+
+# default filters, tests and namespace
+from jinja2.filters import FILTERS as DEFAULT_FILTERS
+from jinja2.tests import TESTS as DEFAULT_TESTS
+DEFAULT_NAMESPACE = {
+    'range':        xrange,
+    'dict':         lambda **kw: kw,
+    'lipsum':       generate_lorem_ipsum,
+    'cycler':       Cycler,
+    'joiner':       Joiner
+}
+
+
+# export all constants
+__all__ = tuple(x for x in locals().keys() if x.isupper())


[29/59] [abbrv] git commit: AMBARI-7148 Need filter for problem properties. (atkach)

Posted by nc...@apache.org.
AMBARI-7148 Need filter for problem properties. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/a537b8e0
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a537b8e0
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a537b8e0

Branch: refs/heads/branch-alerts-dev
Commit: a537b8e0ae6d1f0fdc8ccd3057ec2f3c9eaa1f9e
Parents: 7343cb2
Author: atkach <at...@hortonworks.com>
Authored: Thu Sep 4 15:26:11 2014 +0300
Committer: atkach <at...@hortonworks.com>
Committed: Thu Sep 4 15:26:11 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/main/service/info/configs.js | 9 +++++++++
 ambari-web/app/controllers/wizard/step7_controller.js   | 8 ++++++++
 ambari-web/app/messages.js                              | 1 +
 ambari-web/app/views/common/configs/services_config.js  | 4 ++--
 4 files changed, 20 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/a537b8e0/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index 80e92ea..0c58207 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -128,16 +128,24 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
   propertyFilters: [
     {
       attributeName: 'isOverridden',
+      attributeValue: true,
       caption: 'common.combobox.dropdown.overridden'
     },
     {
       attributeName: 'isFinal',
+      attributeValue: true,
       caption: 'common.combobox.dropdown.final'
     },
     {
       attributeName: 'hasCompareDiffs',
+      attributeValue: true,
       caption: 'common.combobox.dropdown.changed',
       dependentOn: 'isCompareMode'
+    },
+    {
+      attributeName: 'isValid',
+      attributeValue: false,
+      caption: 'common.combobox.dropdown.issues'
     }
   ],
 
@@ -161,6 +169,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
       if (Em.isNone(filter.dependentOn) || this.get(filter.dependentOn)) {
         filterColumns.push(Ember.Object.create({
           attributeName: filter.attributeName,
+          attributeValue: filter.attributeValue,
           name: this.t(filter.caption),
           selected: false
         }));

http://git-wip-us.apache.org/repos/asf/ambari/blob/a537b8e0/ambari-web/app/controllers/wizard/step7_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js
index 9ab5c5a..5679c42 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -202,11 +202,18 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
   propertyFilters: [
     {
       attributeName: 'isOverridden',
+      attributeValue: true,
       caption: 'common.combobox.dropdown.overridden'
     },
     {
       attributeName: 'isFinal',
+      attributeValue: true,
       caption: 'common.combobox.dropdown.final'
+    },
+    {
+      attributeName: 'isValid',
+      attributeValue: false,
+      caption: 'common.combobox.dropdown.issues'
     }
   ],
 
@@ -217,6 +224,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
     return this.get('propertyFilters').map(function(filter) {
       return Ember.Object.create({
         attributeName: filter.attributeName,
+        attributeValue: filter.attributeValue,
         name: this.t(filter.caption),
         selected: false
       })

http://git-wip-us.apache.org/repos/asf/ambari/blob/a537b8e0/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 97dd8db..38b3cdc 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2257,6 +2257,7 @@ Em.I18n.translations = {
   'common.combobox.dropdown.overridden': 'Overridden properties',
   'common.combobox.dropdown.final': 'Final properties',
   'common.combobox.dropdown.changed': 'Changed properties',
+  'common.combobox.dropdown.issues': 'Show property issues',
 
   'quick.links.error.label': 'Hostname is undefined',
   'quick.links.publicHostName': '{0} ({1})',

http://git-wip-us.apache.org/repos/asf/ambari/blob/a537b8e0/ambari-web/app/views/common/configs/services_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/services_config.js b/ambari-web/app/views/common/configs/services_config.js
index 2fc787f..aa189b3 100644
--- a/ambari-web/app/views/common/configs/services_config.js
+++ b/ambari-web/app/views/common/configs/services_config.js
@@ -354,7 +354,7 @@ App.ServiceConfigsByCategoryView = Ember.View.extend(App.UserPref, {
       var passesFilters = true;
 
       selectedFilters.forEach(function (filter) {
-        if (!config.get(filter.attributeName)) {
+        if (config.get(filter.attributeName) !== filter.attributeValue) {
           passesFilters = false;
         }
       });
@@ -397,7 +397,7 @@ App.ServiceConfigsByCategoryView = Ember.View.extend(App.UserPref, {
     var categoryBlock = $('.' + this.get('category.name').split(' ').join('.') + '>.accordion-body');
     filteredResult.length && !this.get('category.isCollapsed') ? categoryBlock.show() : categoryBlock.hide();
     return filteredResult;
-  }.property('categoryConfigs', 'parentView.filter', 'parentView.columns.@each.selected').cacheable(),
+  }.property('categoryConfigs', 'parentView.filter', 'parentView.columns.@each.selected', 'categoryConfigs.@each.isValid').cacheable(),
 
   /**
    * sort configs in current category by index


[47/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py
new file mode 100644
index 0000000..bdb545e
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/filters.py
@@ -0,0 +1,719 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.filters
+    ~~~~~~~~~~~~~~
+
+    Bundled jinja filters.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import math
+from random import choice
+from operator import itemgetter
+from itertools import imap, groupby
+from ambari_jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
+from ambari_jinja2.runtime import Undefined
+from ambari_jinja2.exceptions import FilterArgumentError, SecurityError
+
+
+_word_re = re.compile(r'\w+(?u)')
+
+
+def contextfilter(f):
+    """Decorator for marking context dependent filters. The current
+    :class:`Context` will be passed as first argument.
+    """
+    f.contextfilter = True
+    return f
+
+
+def evalcontextfilter(f):
+    """Decorator for marking eval-context dependent filters.  An eval
+    context object is passed as first argument.  For more information
+    about the eval context, see :ref:`eval-context`.
+
+    .. versionadded:: 2.4
+    """
+    f.evalcontextfilter = True
+    return f
+
+
+def environmentfilter(f):
+    """Decorator for marking evironment dependent filters.  The current
+    :class:`Environment` is passed to the filter as first argument.
+    """
+    f.environmentfilter = True
+    return f
+
+
+def do_forceescape(value):
+    """Enforce HTML escaping.  This will probably double escape variables."""
+    if hasattr(value, '__html__'):
+        value = value.__html__()
+    return escape(unicode(value))
+
+
+@evalcontextfilter
+def do_replace(eval_ctx, s, old, new, count=None):
+    """Return a copy of the value with all occurrences of a substring
+    replaced with a new one. The first argument is the substring
+    that should be replaced, the second is the replacement string.
+    If the optional third argument ``count`` is given, only the first
+    ``count`` occurrences are replaced:
+
+    .. sourcecode:: jinja
+
+        {{ "Hello World"|replace("Hello", "Goodbye") }}
+            -> Goodbye World
+
+        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
+            -> d'oh, d'oh, aaargh
+    """
+    if count is None:
+        count = -1
+    if not eval_ctx.autoescape:
+        return unicode(s).replace(unicode(old), unicode(new), count)
+    if hasattr(old, '__html__') or hasattr(new, '__html__') and \
+       not hasattr(s, '__html__'):
+        s = escape(s)
+    else:
+        s = soft_unicode(s)
+    return s.replace(soft_unicode(old), soft_unicode(new), count)
+
+
+def do_upper(s):
+    """Convert a value to uppercase."""
+    return soft_unicode(s).upper()
+
+
+def do_lower(s):
+    """Convert a value to lowercase."""
+    return soft_unicode(s).lower()
+
+
+@evalcontextfilter
+def do_xmlattr(_eval_ctx, d, autospace=True):
+    """Create an SGML/XML attribute string based on the items in a dict.
+    All values that are neither `none` nor `undefined` are automatically
+    escaped:
+
+    .. sourcecode:: html+jinja
+
+        <ul{{ {'class': 'my_list', 'missing': none,
+                'id': 'list-%d'|format(variable)}|xmlattr }}>
+        ...
+        </ul>
+
+    Results in something like this:
+
+    .. sourcecode:: html
+
+        <ul class="my_list" id="list-42">
+        ...
+        </ul>
+
+    As you can see it automatically prepends a space in front of the item
+    if the filter returned something unless the second parameter is false.
+    """
+    rv = u' '.join(
+        u'%s="%s"' % (escape(key), escape(value))
+        for key, value in d.iteritems()
+        if value is not None and not isinstance(value, Undefined)
+    )
+    if autospace and rv:
+        rv = u' ' + rv
+    if _eval_ctx.autoescape:
+        rv = Markup(rv)
+    return rv
+
+
+def do_capitalize(s):
+    """Capitalize a value. The first character will be uppercase, all others
+    lowercase.
+    """
+    return soft_unicode(s).capitalize()
+
+
+def do_title(s):
+    """Return a titlecased version of the value. I.e. words will start with
+    uppercase letters, all remaining characters are lowercase.
+    """
+    return soft_unicode(s).title()
+
+
+def do_dictsort(value, case_sensitive=False, by='key'):
+    """Sort a dict and yield (key, value) pairs. Because python dicts are
+    unsorted you may want to use this function to order them by either
+    key or value:
+
+    .. sourcecode:: jinja
+
+        {% for item in mydict|dictsort %}
+            sort the dict by key, case insensitive
+
+        {% for item in mydict|dicsort(true) %}
+            sort the dict by key, case sensitive
+
+        {% for item in mydict|dictsort(false, 'value') %}
+            sort the dict by key, case insensitive, sorted
+            normally and ordered by value.
+    """
+    if by == 'key':
+        pos = 0
+    elif by == 'value':
+        pos = 1
+    else:
+        raise FilterArgumentError('You can only sort by either '
+                                  '"key" or "value"')
+    def sort_func(item):
+        value = item[pos]
+        if isinstance(value, basestring) and not case_sensitive:
+            value = value.lower()
+        return value
+
+    return sorted(value.items(), key=sort_func)
+
+
+def do_sort(value, reverse=False, case_sensitive=False):
+    """Sort an iterable.  Per default it sorts ascending, if you pass it
+    true as first argument it will reverse the sorting.
+
+    If the iterable is made of strings the third parameter can be used to
+    control the case sensitiveness of the comparison which is disabled by
+    default.
+
+    .. sourcecode:: jinja
+
+        {% for item in iterable|sort %}
+            ...
+        {% endfor %}
+    """
+    if not case_sensitive:
+        def sort_func(item):
+            if isinstance(item, basestring):
+                item = item.lower()
+            return item
+    else:
+        sort_func = None
+    return sorted(value, key=sort_func, reverse=reverse)
+
+
+def do_default(value, default_value=u'', boolean=False):
+    """If the value is undefined it will return the passed default value,
+    otherwise the value of the variable:
+
+    .. sourcecode:: jinja
+
+        {{ my_variable|default('my_variable is not defined') }}
+
+    This will output the value of ``my_variable`` if the variable was
+    defined, otherwise ``'my_variable is not defined'``. If you want
+    to use default with variables that evaluate to false you have to
+    set the second parameter to `true`:
+
+    .. sourcecode:: jinja
+
+        {{ ''|default('the string was empty', true) }}
+    """
+    if (boolean and not value) or isinstance(value, Undefined):
+        return default_value
+    return value
+
+
+@evalcontextfilter
+def do_join(eval_ctx, value, d=u''):
+    """Return a string which is the concatenation of the strings in the
+    sequence. The separator between elements is an empty string per
+    default, you can define it with the optional parameter:
+
+    .. sourcecode:: jinja
+
+        {{ [1, 2, 3]|join('|') }}
+            -> 1|2|3
+
+        {{ [1, 2, 3]|join }}
+            -> 123
+    """
+    # no automatic escaping?  joining is a lot eaiser then
+    if not eval_ctx.autoescape:
+        return unicode(d).join(imap(unicode, value))
+
+    # if the delimiter doesn't have an html representation we check
+    # if any of the items has.  If yes we do a coercion to Markup
+    if not hasattr(d, '__html__'):
+        value = list(value)
+        do_escape = False
+        for idx, item in enumerate(value):
+            if hasattr(item, '__html__'):
+                do_escape = True
+            else:
+                value[idx] = unicode(item)
+        if do_escape:
+            d = escape(d)
+        else:
+            d = unicode(d)
+        return d.join(value)
+
+    # no html involved, to normal joining
+    return soft_unicode(d).join(imap(soft_unicode, value))
+
+
+def do_center(value, width=80):
+    """Centers the value in a field of a given width."""
+    return unicode(value).center(width)
+
+
+@environmentfilter
+def do_first(environment, seq):
+    """Return the first item of a sequence."""
+    try:
+        return iter(seq).next()
+    except StopIteration:
+        return environment.undefined('No first item, sequence was empty.')
+
+
+@environmentfilter
+def do_last(environment, seq):
+    """Return the last item of a sequence."""
+    try:
+        return iter(reversed(seq)).next()
+    except StopIteration:
+        return environment.undefined('No last item, sequence was empty.')
+
+
+@environmentfilter
+def do_random(environment, seq):
+    """Return a random item from the sequence."""
+    try:
+        return choice(seq)
+    except IndexError:
+        return environment.undefined('No random item, sequence was empty.')
+
+
+def do_filesizeformat(value, binary=False):
+    """Format the value like a 'human-readable' file size (i.e. 13 KB,
+    4.1 MB, 102 bytes, etc).  Per default decimal prefixes are used (mega,
+    giga, etc.), if the second parameter is set to `True` the binary
+    prefixes are used (mebi, gibi).
+    """
+    bytes = float(value)
+    base = binary and 1024 or 1000
+    middle = binary and 'i' or ''
+    if bytes < base:
+        return "%d Byte%s" % (bytes, bytes != 1 and 's' or '')
+    elif bytes < base * base:
+        return "%.1f K%sB" % (bytes / base, middle)
+    elif bytes < base * base * base:
+        return "%.1f M%sB" % (bytes / (base * base), middle)
+    return "%.1f G%sB" % (bytes / (base * base * base), middle)
+
+
+def do_pprint(value, verbose=False):
+    """Pretty print a variable. Useful for debugging.
+
+    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
+    is truthy the output will be more verbose (this requires `pretty`)
+    """
+    return pformat(value, verbose=verbose)
+
+
+@evalcontextfilter
+def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
+    """Converts URLs in plain text into clickable links.
+
+    If you pass the filter an additional integer it will shorten the urls
+    to that number. Also a third argument exists that makes the urls
+    "nofollow":
+
+    .. sourcecode:: jinja
+
+        {{ mytext|urlize(40, true) }}
+            links are shortened to 40 chars and defined with rel="nofollow"
+    """
+    rv = urlize(value, trim_url_limit, nofollow)
+    if eval_ctx.autoescape:
+        rv = Markup(rv)
+    return rv
+
+
+def do_indent(s, width=4, indentfirst=False):
+    """Return a copy of the passed string, each line indented by
+    4 spaces. The first line is not indented. If you want to
+    change the number of spaces or indent the first line too
+    you can pass additional parameters to the filter:
+
+    .. sourcecode:: jinja
+
+        {{ mytext|indent(2, true) }}
+            indent by two spaces and indent the first line too.
+    """
+    indention = u' ' * width
+    rv = (u'\n' + indention).join(s.splitlines())
+    if indentfirst:
+        rv = indention + rv
+    return rv
+
+
+def do_truncate(s, length=255, killwords=False, end='...'):
+    """Return a truncated copy of the string. The length is specified
+    with the first parameter which defaults to ``255``. If the second
+    parameter is ``true`` the filter will cut the text at length. Otherwise
+    it will try to save the last word. If the text was in fact
+    truncated it will append an ellipsis sign (``"..."``). If you want a
+    different ellipsis sign than ``"..."`` you can specify it using the
+    third parameter.
+
+    .. sourcecode jinja::
+
+        {{ mytext|truncate(300, false, '&raquo;') }}
+            truncate mytext to 300 chars, don't split up words, use a
+            right pointing double arrow as ellipsis sign.
+    """
+    if len(s) <= length:
+        return s
+    elif killwords:
+        return s[:length] + end
+    words = s.split(' ')
+    result = []
+    m = 0
+    for word in words:
+        m += len(word) + 1
+        if m > length:
+            break
+        result.append(word)
+    result.append(end)
+    return u' '.join(result)
+
+
+def do_wordwrap(s, width=79, break_long_words=True):
+    """
+    Return a copy of the string passed to the filter wrapped after
+    ``79`` characters.  You can override this default using the first
+    parameter.  If you set the second parameter to `false` Jinja will not
+    split words apart if they are longer than `width`.
+    """
+    import textwrap
+    return u'\n'.join(textwrap.wrap(s, width=width, expand_tabs=False,
+                                   replace_whitespace=False,
+                                   break_long_words=break_long_words))
+
+
+def do_wordcount(s):
+    """Count the words in that string."""
+    return len(_word_re.findall(s))
+
+
+def do_int(value, default=0):
+    """Convert the value into an integer. If the
+    conversion doesn't work it will return ``0``. You can
+    override this default using the first parameter.
+    """
+    try:
+        return int(value)
+    except (TypeError, ValueError):
+        # this quirk is necessary so that "42.23"|int gives 42.
+        try:
+            return int(float(value))
+        except (TypeError, ValueError):
+            return default
+
+
+def do_float(value, default=0.0):
+    """Convert the value into a floating point number. If the
+    conversion doesn't work it will return ``0.0``. You can
+    override this default using the first parameter.
+    """
+    try:
+        return float(value)
+    except (TypeError, ValueError):
+        return default
+
+
+def do_format(value, *args, **kwargs):
+    """
+    Apply python string formatting on an object:
+
+    .. sourcecode:: jinja
+
+        {{ "%s - %s"|format("Hello?", "Foo!") }}
+            -> Hello? - Foo!
+    """
+    if args and kwargs:
+        raise FilterArgumentError('can\'t handle positional and keyword '
+                                  'arguments at the same time')
+    return soft_unicode(value) % (kwargs or args)
+
+
+def do_trim(value):
+    """Strip leading and trailing whitespace."""
+    return soft_unicode(value).strip()
+
+
+def do_striptags(value):
+    """Strip SGML/XML tags and replace adjacent whitespace by one space.
+    """
+    if hasattr(value, '__html__'):
+        value = value.__html__()
+    return Markup(unicode(value)).striptags()
+
+
+def do_slice(value, slices, fill_with=None):
+    """Slice an iterator and return a list of lists containing
+    those items. Useful if you want to create a div containing
+    three ul tags that represent columns:
+
+    .. sourcecode:: html+jinja
+
+        <div class="columwrapper">
+          {%- for column in items|slice(3) %}
+            <ul class="column-{{ loop.index }}">
+            {%- for item in column %}
+              <li>{{ item }}</li>
+            {%- endfor %}
+            </ul>
+          {%- endfor %}
+        </div>
+
+    If you pass it a second argument it's used to fill missing
+    values on the last iteration.
+    """
+    seq = list(value)
+    length = len(seq)
+    items_per_slice = length // slices
+    slices_with_extra = length % slices
+    offset = 0
+    for slice_number in xrange(slices):
+        start = offset + slice_number * items_per_slice
+        if slice_number < slices_with_extra:
+            offset += 1
+        end = offset + (slice_number + 1) * items_per_slice
+        tmp = seq[start:end]
+        if fill_with is not None and slice_number >= slices_with_extra:
+            tmp.append(fill_with)
+        yield tmp
+
+
+def do_batch(value, linecount, fill_with=None):
+    """
+    A filter that batches items. It works pretty much like `slice`
+    just the other way round. It returns a list of lists with the
+    given number of items. If you provide a second parameter this
+    is used to fill missing items. See this example:
+
+    .. sourcecode:: html+jinja
+
+        <table>
+        {%- for row in items|batch(3, '&nbsp;') %}
+          <tr>
+          {%- for column in row %}
+            <td>{{ column }}</td>
+          {%- endfor %}
+          </tr>
+        {%- endfor %}
+        </table>
+    """
+    result = []
+    tmp = []
+    for item in value:
+        if len(tmp) == linecount:
+            yield tmp
+            tmp = []
+        tmp.append(item)
+    if tmp:
+        if fill_with is not None and len(tmp) < linecount:
+            tmp += [fill_with] * (linecount - len(tmp))
+        yield tmp
+
+
+def do_round(value, precision=0, method='common'):
+    """Round the number to a given precision. The first
+    parameter specifies the precision (default is ``0``), the
+    second the rounding method:
+
+    - ``'common'`` rounds either up or down
+    - ``'ceil'`` always rounds up
+    - ``'floor'`` always rounds down
+
+    If you don't specify a method ``'common'`` is used.
+
+    .. sourcecode:: jinja
+
+        {{ 42.55|round }}
+            -> 43.0
+        {{ 42.55|round(1, 'floor') }}
+            -> 42.5
+
+    Note that even if rounded to 0 precision, a float is returned.  If
+    you need a real integer, pipe it through `int`:
+
+    .. sourcecode:: jinja
+
+        {{ 42.55|round|int }}
+            -> 43
+    """
+    if not method in ('common', 'ceil', 'floor'):
+        raise FilterArgumentError('method must be common, ceil or floor')
+    if method == 'common':
+        return round(value, precision)
+    func = getattr(math, method)
+    return func(value * (10 ** precision)) / (10 ** precision)
+
+
+@environmentfilter
+def do_groupby(environment, value, attribute):
+    """Group a sequence of objects by a common attribute.
+
+    If you for example have a list of dicts or objects that represent persons
+    with `gender`, `first_name` and `last_name` attributes and you want to
+    group all users by genders you can do something like the following
+    snippet:
+
+    .. sourcecode:: html+jinja
+
+        <ul>
+        {% for group in persons|groupby('gender') %}
+            <li>{{ group.grouper }}<ul>
+            {% for person in group.list %}
+                <li>{{ person.first_name }} {{ person.last_name }}</li>
+            {% endfor %}</ul></li>
+        {% endfor %}
+        </ul>
+
+    Additionally it's possible to use tuple unpacking for the grouper and
+    list:
+
+    .. sourcecode:: html+jinja
+
+        <ul>
+        {% for grouper, list in persons|groupby('gender') %}
+            ...
+        {% endfor %}
+        </ul>
+
+    As you can see the item we're grouping by is stored in the `grouper`
+    attribute and the `list` contains all the objects that have this grouper
+    in common.
+    """
+    expr = lambda x: environment.getitem(x, attribute)
+    return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
+
+
+class _GroupTuple(tuple):
+    __slots__ = ()
+    grouper = property(itemgetter(0))
+    list = property(itemgetter(1))
+
+    def __new__(cls, (key, value)):
+        return tuple.__new__(cls, (key, list(value)))
+
+
+def do_list(value):
+    """Convert the value into a list.  If it was a string the returned list
+    will be a list of characters.
+    """
+    return list(value)
+
+
+def do_mark_safe(value):
+    """Mark the value as safe which means that in an environment with automatic
+    escaping enabled this variable will not be escaped.
+    """
+    return Markup(value)
+
+
+def do_mark_unsafe(value):
+    """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
+    return unicode(value)
+
+
+def do_reverse(value):
+    """Reverse the object or return an iterator the iterates over it the other
+    way round.
+    """
+    if isinstance(value, basestring):
+        return value[::-1]
+    try:
+        return reversed(value)
+    except TypeError:
+        try:
+            rv = list(value)
+            rv.reverse()
+            return rv
+        except TypeError:
+            raise FilterArgumentError('argument must be iterable')
+
+
+@environmentfilter
+def do_attr(environment, obj, name):
+    """Get an attribute of an object.  ``foo|attr("bar")`` works like
+    ``foo["bar"]`` just that always an attribute is returned and items are not
+    looked up.
+
+    See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
+    """
+    try:
+        name = str(name)
+    except UnicodeError:
+        pass
+    else:
+        try:
+            value = getattr(obj, name)
+        except AttributeError:
+            pass
+        else:
+            if environment.sandboxed and not \
+               environment.is_safe_attribute(obj, name, value):
+                return environment.unsafe_undefined(obj, name)
+            return value
+    return environment.undefined(obj=obj, name=name)
+
+
+FILTERS = {
+    'attr':                 do_attr,
+    'replace':              do_replace,
+    'upper':                do_upper,
+    'lower':                do_lower,
+    'escape':               escape,
+    'e':                    escape,
+    'forceescape':          do_forceescape,
+    'capitalize':           do_capitalize,
+    'title':                do_title,
+    'default':              do_default,
+    'd':                    do_default,
+    'join':                 do_join,
+    'count':                len,
+    'dictsort':             do_dictsort,
+    'sort':                 do_sort,
+    'length':               len,
+    'reverse':              do_reverse,
+    'center':               do_center,
+    'indent':               do_indent,
+    'title':                do_title,
+    'capitalize':           do_capitalize,
+    'first':                do_first,
+    'last':                 do_last,
+    'random':               do_random,
+    'filesizeformat':       do_filesizeformat,
+    'pprint':               do_pprint,
+    'truncate':             do_truncate,
+    'wordwrap':             do_wordwrap,
+    'wordcount':            do_wordcount,
+    'int':                  do_int,
+    'float':                do_float,
+    'string':               soft_unicode,
+    'list':                 do_list,
+    'urlize':               do_urlize,
+    'format':               do_format,
+    'trim':                 do_trim,
+    'striptags':            do_striptags,
+    'slice':                do_slice,
+    'batch':                do_batch,
+    'sum':                  sum,
+    'abs':                  abs,
+    'round':                do_round,
+    'groupby':              do_groupby,
+    'safe':                 do_mark_safe,
+    'xmlattr':              do_xmlattr
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py
new file mode 100644
index 0000000..0c385c1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/lexer.py
@@ -0,0 +1,681 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.lexer
+    ~~~~~~~~~~~~
+
+    This module implements a Jinja / Python combination lexer. The
+    `Lexer` class provided by this module is used to do some preprocessing
+    for Jinja.
+
+    On the one hand it filters out invalid operators like the bitshift
+    operators we don't allow in templates. On the other hand it separates
+    template code and python code in expressions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+from operator import itemgetter
+from collections import deque
+from ambari_jinja2.exceptions import TemplateSyntaxError
+from ambari_jinja2.utils import LRUCache, next
+
+
+# cache for the lexers. Exists in order to be able to have multiple
+# environments with the same lexer
+_lexer_cache = LRUCache(50)
+
+# static regular expressions
+whitespace_re = re.compile(r'\s+', re.U)
+string_re = re.compile(r"('([^'\\]*(?:\\.[^'\\]*)*)'"
+                       r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
+integer_re = re.compile(r'\d+')
+
+# we use the unicode identifier rule if this python version is able
+# to handle unicode identifiers, otherwise the standard ASCII one.
+try:
+    compile('föö', '<unknown>', 'eval')
+except SyntaxError:
+    name_re = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b')
+else:
+    from ambari_jinja2 import _stringdefs
+    name_re = re.compile(r'[%s][%s]*' % (_stringdefs.xid_start,
+                                         _stringdefs.xid_continue))
+
+float_re = re.compile(r'(?<!\.)\d+\.\d+')
+newline_re = re.compile(r'(\r\n|\r|\n)')
+
+# internal the tokens and keep references to them
+TOKEN_ADD = intern('add')
+TOKEN_ASSIGN = intern('assign')
+TOKEN_COLON = intern('colon')
+TOKEN_COMMA = intern('comma')
+TOKEN_DIV = intern('div')
+TOKEN_DOT = intern('dot')
+TOKEN_EQ = intern('eq')
+TOKEN_FLOORDIV = intern('floordiv')
+TOKEN_GT = intern('gt')
+TOKEN_GTEQ = intern('gteq')
+TOKEN_LBRACE = intern('lbrace')
+TOKEN_LBRACKET = intern('lbracket')
+TOKEN_LPAREN = intern('lparen')
+TOKEN_LT = intern('lt')
+TOKEN_LTEQ = intern('lteq')
+TOKEN_MOD = intern('mod')
+TOKEN_MUL = intern('mul')
+TOKEN_NE = intern('ne')
+TOKEN_PIPE = intern('pipe')
+TOKEN_POW = intern('pow')
+TOKEN_RBRACE = intern('rbrace')
+TOKEN_RBRACKET = intern('rbracket')
+TOKEN_RPAREN = intern('rparen')
+TOKEN_SEMICOLON = intern('semicolon')
+TOKEN_SUB = intern('sub')
+TOKEN_TILDE = intern('tilde')
+TOKEN_WHITESPACE = intern('whitespace')
+TOKEN_FLOAT = intern('float')
+TOKEN_INTEGER = intern('integer')
+TOKEN_NAME = intern('name')
+TOKEN_STRING = intern('string')
+TOKEN_OPERATOR = intern('operator')
+TOKEN_BLOCK_BEGIN = intern('block_begin')
+TOKEN_BLOCK_END = intern('block_end')
+TOKEN_VARIABLE_BEGIN = intern('variable_begin')
+TOKEN_VARIABLE_END = intern('variable_end')
+TOKEN_RAW_BEGIN = intern('raw_begin')
+TOKEN_RAW_END = intern('raw_end')
+TOKEN_COMMENT_BEGIN = intern('comment_begin')
+TOKEN_COMMENT_END = intern('comment_end')
+TOKEN_COMMENT = intern('comment')
+TOKEN_LINESTATEMENT_BEGIN = intern('linestatement_begin')
+TOKEN_LINESTATEMENT_END = intern('linestatement_end')
+TOKEN_LINECOMMENT_BEGIN = intern('linecomment_begin')
+TOKEN_LINECOMMENT_END = intern('linecomment_end')
+TOKEN_LINECOMMENT = intern('linecomment')
+TOKEN_DATA = intern('data')
+TOKEN_INITIAL = intern('initial')
+TOKEN_EOF = intern('eof')
+
+# bind operators to token types
+operators = {
+    '+':            TOKEN_ADD,
+    '-':            TOKEN_SUB,
+    '/':            TOKEN_DIV,
+    '//':           TOKEN_FLOORDIV,
+    '*':            TOKEN_MUL,
+    '%':            TOKEN_MOD,
+    '**':           TOKEN_POW,
+    '~':            TOKEN_TILDE,
+    '[':            TOKEN_LBRACKET,
+    ']':            TOKEN_RBRACKET,
+    '(':            TOKEN_LPAREN,
+    ')':            TOKEN_RPAREN,
+    '{':            TOKEN_LBRACE,
+    '}':            TOKEN_RBRACE,
+    '==':           TOKEN_EQ,
+    '!=':           TOKEN_NE,
+    '>':            TOKEN_GT,
+    '>=':           TOKEN_GTEQ,
+    '<':            TOKEN_LT,
+    '<=':           TOKEN_LTEQ,
+    '=':            TOKEN_ASSIGN,
+    '.':            TOKEN_DOT,
+    ':':            TOKEN_COLON,
+    '|':            TOKEN_PIPE,
+    ',':            TOKEN_COMMA,
+    ';':            TOKEN_SEMICOLON
+}
+
+reverse_operators = dict([(v, k) for k, v in operators.iteritems()])
+assert len(operators) == len(reverse_operators), 'operators dropped'
+operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
+                         sorted(operators, key=lambda x: -len(x))))
+
+ignored_tokens = frozenset([TOKEN_COMMENT_BEGIN, TOKEN_COMMENT,
+                            TOKEN_COMMENT_END, TOKEN_WHITESPACE,
+                            TOKEN_WHITESPACE, TOKEN_LINECOMMENT_BEGIN,
+                            TOKEN_LINECOMMENT_END, TOKEN_LINECOMMENT])
+ignore_if_empty = frozenset([TOKEN_WHITESPACE, TOKEN_DATA,
+                             TOKEN_COMMENT, TOKEN_LINECOMMENT])
+
+
+def _describe_token_type(token_type):
+    if token_type in reverse_operators:
+        return reverse_operators[token_type]
+    return {
+        TOKEN_COMMENT_BEGIN:        'begin of comment',
+        TOKEN_COMMENT_END:          'end of comment',
+        TOKEN_COMMENT:              'comment',
+        TOKEN_LINECOMMENT:          'comment',
+        TOKEN_BLOCK_BEGIN:          'begin of statement block',
+        TOKEN_BLOCK_END:            'end of statement block',
+        TOKEN_VARIABLE_BEGIN:       'begin of print statement',
+        TOKEN_VARIABLE_END:         'end of print statement',
+        TOKEN_LINESTATEMENT_BEGIN:  'begin of line statement',
+        TOKEN_LINESTATEMENT_END:    'end of line statement',
+        TOKEN_DATA:                 'template data / text',
+        TOKEN_EOF:                  'end of template'
+    }.get(token_type, token_type)
+
+
+def describe_token(token):
+    """Returns a description of the token."""
+    if token.type == 'name':
+        return token.value
+    return _describe_token_type(token.type)
+
+
+def describe_token_expr(expr):
+    """Like `describe_token` but for token expressions."""
+    if ':' in expr:
+        type, value = expr.split(':', 1)
+        if type == 'name':
+            return value
+    else:
+        type = expr
+    return _describe_token_type(type)
+
+
+def count_newlines(value):
+    """Count the number of newline characters in the string.  This is
+    useful for extensions that filter a stream.
+    """
+    return len(newline_re.findall(value))
+
+
+def compile_rules(environment):
+    """Compiles all the rules from the environment into a list of rules."""
+    e = re.escape
+    rules = [
+        (len(environment.comment_start_string), 'comment',
+         e(environment.comment_start_string)),
+        (len(environment.block_start_string), 'block',
+         e(environment.block_start_string)),
+        (len(environment.variable_start_string), 'variable',
+         e(environment.variable_start_string))
+    ]
+
+    if environment.line_statement_prefix is not None:
+        rules.append((len(environment.line_statement_prefix), 'linestatement',
+                      r'^\s*' + e(environment.line_statement_prefix)))
+    if environment.line_comment_prefix is not None:
+        rules.append((len(environment.line_comment_prefix), 'linecomment',
+                      r'(?:^|(?<=\S))[^\S\r\n]*' +
+                      e(environment.line_comment_prefix)))
+
+    return [x[1:] for x in sorted(rules, reverse=True)]
+
+
+class Failure(object):
+    """Class that raises a `TemplateSyntaxError` if called.
+    Used by the `Lexer` to specify known errors.
+    """
+
+    def __init__(self, message, cls=TemplateSyntaxError):
+        self.message = message
+        self.error_class = cls
+
+    def __call__(self, lineno, filename):
+        raise self.error_class(self.message, lineno, filename)
+
+
+class Token(tuple):
+    """Token class."""
+    __slots__ = ()
+    lineno, type, value = (property(itemgetter(x)) for x in range(3))
+
+    def __new__(cls, lineno, type, value):
+        return tuple.__new__(cls, (lineno, intern(str(type)), value))
+
+    def __str__(self):
+        if self.type in reverse_operators:
+            return reverse_operators[self.type]
+        elif self.type == 'name':
+            return self.value
+        return self.type
+
+    def test(self, expr):
+        """Test a token against a token expression.  This can either be a
+        token type or ``'token_type:token_value'``.  This can only test
+        against string values and types.
+        """
+        # here we do a regular string equality check as test_any is usually
+        # passed an iterable of not interned strings.
+        if self.type == expr:
+            return True
+        elif ':' in expr:
+            return expr.split(':', 1) == [self.type, self.value]
+        return False
+
+    def test_any(self, *iterable):
+        """Test against multiple token expressions."""
+        for expr in iterable:
+            if self.test(expr):
+                return True
+        return False
+
+    def __repr__(self):
+        return 'Token(%r, %r, %r)' % (
+            self.lineno,
+            self.type,
+            self.value
+        )
+
+
+class TokenStreamIterator(object):
+    """The iterator for tokenstreams.  Iterate over the stream
+    until the eof token is reached.
+    """
+
+    def __init__(self, stream):
+        self.stream = stream
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        token = self.stream.current
+        if token.type is TOKEN_EOF:
+            self.stream.close()
+            raise StopIteration()
+        next(self.stream)
+        return token
+
+
+class TokenStream(object):
+    """A token stream is an iterable that yields :class:`Token`\s.  The
+    parser however does not iterate over it but calls :meth:`next` to go
+    one token ahead.  The current active token is stored as :attr:`current`.
+    """
+
+    def __init__(self, generator, name, filename):
+        self._next = iter(generator).next
+        self._pushed = deque()
+        self.name = name
+        self.filename = filename
+        self.closed = False
+        self.current = Token(1, TOKEN_INITIAL, '')
+        next(self)
+
+    def __iter__(self):
+        return TokenStreamIterator(self)
+
+    def __nonzero__(self):
+        return bool(self._pushed) or self.current.type is not TOKEN_EOF
+
+    eos = property(lambda x: not x, doc="Are we at the end of the stream?")
+
+    def push(self, token):
+        """Push a token back to the stream."""
+        self._pushed.append(token)
+
+    def look(self):
+        """Look at the next token."""
+        old_token = next(self)
+        result = self.current
+        self.push(result)
+        self.current = old_token
+        return result
+
+    def skip(self, n=1):
+        """Got n tokens ahead."""
+        for x in xrange(n):
+            next(self)
+
+    def next_if(self, expr):
+        """Perform the token test and return the token if it matched.
+        Otherwise the return value is `None`.
+        """
+        if self.current.test(expr):
+            return next(self)
+
+    def skip_if(self, expr):
+        """Like :meth:`next_if` but only returns `True` or `False`."""
+        return self.next_if(expr) is not None
+
+    def next(self):
+        """Go one token ahead and return the old one"""
+        rv = self.current
+        if self._pushed:
+            self.current = self._pushed.popleft()
+        elif self.current.type is not TOKEN_EOF:
+            try:
+                self.current = self._next()
+            except StopIteration:
+                self.close()
+        return rv
+
+    def close(self):
+        """Close the stream."""
+        self.current = Token(self.current.lineno, TOKEN_EOF, '')
+        self._next = None
+        self.closed = True
+
+    def expect(self, expr):
+        """Expect a given token type and return it.  This accepts the same
+        argument as :meth:`ambari_jinja2.lexer.Token.test`.
+        """
+        if not self.current.test(expr):
+            expr = describe_token_expr(expr)
+            if self.current.type is TOKEN_EOF:
+                raise TemplateSyntaxError('unexpected end of template, '
+                                          'expected %r.' % expr,
+                                          self.current.lineno,
+                                          self.name, self.filename)
+            raise TemplateSyntaxError("expected token %r, got %r" %
+                                      (expr, describe_token(self.current)),
+                                      self.current.lineno,
+                                      self.name, self.filename)
+        try:
+            return self.current
+        finally:
+            next(self)
+
+
+def get_lexer(environment):
+    """Return a lexer which is probably cached."""
+    key = (environment.block_start_string,
+           environment.block_end_string,
+           environment.variable_start_string,
+           environment.variable_end_string,
+           environment.comment_start_string,
+           environment.comment_end_string,
+           environment.line_statement_prefix,
+           environment.line_comment_prefix,
+           environment.trim_blocks,
+           environment.newline_sequence)
+    lexer = _lexer_cache.get(key)
+    if lexer is None:
+        lexer = Lexer(environment)
+        _lexer_cache[key] = lexer
+    return lexer
+
+
+class Lexer(object):
+    """Class that implements a lexer for a given environment. Automatically
+    created by the environment class, usually you don't have to do that.
+
+    Note that the lexer is not automatically bound to an environment.
+    Multiple environments can share the same lexer.
+    """
+
+    def __init__(self, environment):
+        # shortcuts
+        c = lambda x: re.compile(x, re.M | re.S)
+        e = re.escape
+
+        # lexing rules for tags
+        tag_rules = [
+            (whitespace_re, TOKEN_WHITESPACE, None),
+            (float_re, TOKEN_FLOAT, None),
+            (integer_re, TOKEN_INTEGER, None),
+            (name_re, TOKEN_NAME, None),
+            (string_re, TOKEN_STRING, None),
+            (operator_re, TOKEN_OPERATOR, None)
+        ]
+
+        # assamble the root lexing rule. because "|" is ungreedy
+        # we have to sort by length so that the lexer continues working
+        # as expected when we have parsing rules like <% for block and
+        # <%= for variables. (if someone wants asp like syntax)
+        # variables are just part of the rules if variable processing
+        # is required.
+        root_tag_rules = compile_rules(environment)
+
+        # block suffix if trimming is enabled
+        block_suffix_re = environment.trim_blocks and '\\n?' or ''
+
+        self.newline_sequence = environment.newline_sequence
+
+        # global lexing rules
+        self.rules = {
+            'root': [
+                # directives
+                (c('(.*?)(?:%s)' % '|'.join(
+                    [r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
+                        e(environment.block_start_string),
+                        e(environment.block_start_string),
+                        e(environment.block_end_string),
+                        e(environment.block_end_string)
+                    )] + [
+                        r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, r)
+                        for n, r in root_tag_rules
+                    ])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
+                # data
+                (c('.+'), TOKEN_DATA, None)
+            ],
+            # comments
+            TOKEN_COMMENT_BEGIN: [
+                (c(r'(.*?)((?:\-%s\s*|%s)%s)' % (
+                    e(environment.comment_end_string),
+                    e(environment.comment_end_string),
+                    block_suffix_re
+                )), (TOKEN_COMMENT, TOKEN_COMMENT_END), '#pop'),
+                (c('(.)'), (Failure('Missing end of comment tag'),), None)
+            ],
+            # blocks
+            TOKEN_BLOCK_BEGIN: [
+                (c('(?:\-%s\s*|%s)%s' % (
+                    e(environment.block_end_string),
+                    e(environment.block_end_string),
+                    block_suffix_re
+                )), TOKEN_BLOCK_END, '#pop'),
+            ] + tag_rules,
+            # variables
+            TOKEN_VARIABLE_BEGIN: [
+                (c('\-%s\s*|%s' % (
+                    e(environment.variable_end_string),
+                    e(environment.variable_end_string)
+                )), TOKEN_VARIABLE_END, '#pop')
+            ] + tag_rules,
+            # raw block
+            TOKEN_RAW_BEGIN: [
+                (c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
+                    e(environment.block_start_string),
+                    e(environment.block_start_string),
+                    e(environment.block_end_string),
+                    e(environment.block_end_string),
+                    block_suffix_re
+                )), (TOKEN_DATA, TOKEN_RAW_END), '#pop'),
+                (c('(.)'), (Failure('Missing end of raw directive'),), None)
+            ],
+            # line statements
+            TOKEN_LINESTATEMENT_BEGIN: [
+                (c(r'\s*(\n|$)'), TOKEN_LINESTATEMENT_END, '#pop')
+            ] + tag_rules,
+            # line comments
+            TOKEN_LINECOMMENT_BEGIN: [
+                (c(r'(.*?)()(?=\n|$)'), (TOKEN_LINECOMMENT,
+                 TOKEN_LINECOMMENT_END), '#pop')
+            ]
+        }
+
+    def _normalize_newlines(self, value):
+        """Called for strings and template data to normlize it to unicode."""
+        return newline_re.sub(self.newline_sequence, value)
+
+    def tokenize(self, source, name=None, filename=None, state=None):
+        """Calls tokeniter + tokenize and wraps it in a token stream.
+        """
+        stream = self.tokeniter(source, name, filename, state)
+        return TokenStream(self.wrap(stream, name, filename), name, filename)
+
+    def wrap(self, stream, name=None, filename=None):
+        """This is called with the stream as returned by `tokenize` and wraps
+        every token in a :class:`Token` and converts the value.
+        """
+        for lineno, token, value in stream:
+            if token in ignored_tokens:
+                continue
+            elif token == 'linestatement_begin':
+                token = 'block_begin'
+            elif token == 'linestatement_end':
+                token = 'block_end'
+            # we are not interested in those tokens in the parser
+            elif token in ('raw_begin', 'raw_end'):
+                continue
+            elif token == 'data':
+                value = self._normalize_newlines(value)
+            elif token == 'keyword':
+                token = value
+            elif token == 'name':
+                value = str(value)
+            elif token == 'string':
+                # try to unescape string
+                try:
+                    value = self._normalize_newlines(value[1:-1]) \
+                        .encode('ascii', 'backslashreplace') \
+                        .decode('unicode-escape')
+                except Exception, e:
+                    msg = str(e).split(':')[-1].strip()
+                    raise TemplateSyntaxError(msg, lineno, name, filename)
+                # if we can express it as bytestring (ascii only)
+                # we do that for support of semi broken APIs
+                # as datetime.datetime.strftime.  On python 3 this
+                # call becomes a noop thanks to 2to3
+                try:
+                    value = str(value)
+                except UnicodeError:
+                    pass
+            elif token == 'integer':
+                value = int(value)
+            elif token == 'float':
+                value = float(value)
+            elif token == 'operator':
+                token = operators[value]
+            yield Token(lineno, token, value)
+
+    def tokeniter(self, source, name, filename=None, state=None):
+        """This method tokenizes the text and returns the tokens in a
+        generator.  Use this method if you just want to tokenize a template.
+        """
+        source = '\n'.join(unicode(source).splitlines())
+        pos = 0
+        lineno = 1
+        stack = ['root']
+        if state is not None and state != 'root':
+            assert state in ('variable', 'block'), 'invalid state'
+            stack.append(state + '_begin')
+        else:
+            state = 'root'
+        statetokens = self.rules[stack[-1]]
+        source_length = len(source)
+
+        balancing_stack = []
+
+        while 1:
+            # tokenizer loop
+            for regex, tokens, new_state in statetokens:
+                m = regex.match(source, pos)
+                # if no match we try again with the next rule
+                if m is None:
+                    continue
+
+                # we only match blocks and variables if brances / parentheses
+                # are balanced. continue parsing with the lower rule which
+                # is the operator rule. do this only if the end tags look
+                # like operators
+                if balancing_stack and \
+                   tokens in ('variable_end', 'block_end',
+                              'linestatement_end'):
+                    continue
+
+                # tuples support more options
+                if isinstance(tokens, tuple):
+                    for idx, token in enumerate(tokens):
+                        # failure group
+                        if token.__class__ is Failure:
+                            raise token(lineno, filename)
+                        # bygroup is a bit more complex, in that case we
+                        # yield for the current token the first named
+                        # group that matched
+                        elif token == '#bygroup':
+                            for key, value in m.groupdict().iteritems():
+                                if value is not None:
+                                    yield lineno, key, value
+                                    lineno += value.count('\n')
+                                    break
+                            else:
+                                raise RuntimeError('%r wanted to resolve '
+                                                   'the token dynamically'
+                                                   ' but no group matched'
+                                                   % regex)
+                        # normal group
+                        else:
+                            data = m.group(idx + 1)
+                            if data or token not in ignore_if_empty:
+                                yield lineno, token, data
+                            lineno += data.count('\n')
+
+                # strings as token just are yielded as it.
+                else:
+                    data = m.group()
+                    # update brace/parentheses balance
+                    if tokens == 'operator':
+                        if data == '{':
+                            balancing_stack.append('}')
+                        elif data == '(':
+                            balancing_stack.append(')')
+                        elif data == '[':
+                            balancing_stack.append(']')
+                        elif data in ('}', ')', ']'):
+                            if not balancing_stack:
+                                raise TemplateSyntaxError('unexpected \'%s\'' %
+                                                          data, lineno, name,
+                                                          filename)
+                            expected_op = balancing_stack.pop()
+                            if expected_op != data:
+                                raise TemplateSyntaxError('unexpected \'%s\', '
+                                                          'expected \'%s\'' %
+                                                          (data, expected_op),
+                                                          lineno, name,
+                                                          filename)
+                    # yield items
+                    if data or tokens not in ignore_if_empty:
+                        yield lineno, tokens, data
+                    lineno += data.count('\n')
+
+                # fetch new position into new variable so that we can check
+                # if there is a internal parsing error which would result
+                # in an infinite loop
+                pos2 = m.end()
+
+                # handle state changes
+                if new_state is not None:
+                    # remove the uppermost state
+                    if new_state == '#pop':
+                        stack.pop()
+                    # resolve the new state by group checking
+                    elif new_state == '#bygroup':
+                        for key, value in m.groupdict().iteritems():
+                            if value is not None:
+                                stack.append(key)
+                                break
+                        else:
+                            raise RuntimeError('%r wanted to resolve the '
+                                               'new state dynamically but'
+                                               ' no group matched' %
+                                               regex)
+                    # direct state name given
+                    else:
+                        stack.append(new_state)
+                    statetokens = self.rules[stack[-1]]
+                # we are still at the same position and no stack change.
+                # this means a loop without break condition, avoid that and
+                # raise error
+                elif pos2 == pos:
+                    raise RuntimeError('%r yielded empty string without '
+                                       'stack change' % regex)
+                # publish new function and start again
+                pos = pos2
+                break
+            # if loop terminated without break we havn't found a single match
+            # either we are at the end of the file or we have a problem
+            else:
+                # end of text
+                if pos >= source_length:
+                    return
+                # something went wrong
+                raise TemplateSyntaxError('unexpected char %r at %d' %
+                                          (source[pos], pos), lineno,
+                                          name, filename)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py
new file mode 100644
index 0000000..b25be08
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/loaders.py
@@ -0,0 +1,449 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.loaders
+    ~~~~~~~~~~~~~~
+
+    Jinja loader classes.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import weakref
+from types import ModuleType
+from os import path
+try:
+    from hashlib import sha1
+except ImportError:
+    from sha import new as sha1
+from ambari_jinja2.exceptions import TemplateNotFound
+from ambari_jinja2.utils import LRUCache, open_if_exists, internalcode
+
+
+def split_template_path(template):
+    """Split a path into segments and perform a sanity check.  If it detects
+    '..' in the path it will raise a `TemplateNotFound` error.
+    """
+    pieces = []
+    for piece in template.split('/'):
+        if path.sep in piece \
+           or (path.altsep and path.altsep in piece) or \
+           piece == path.pardir:
+            raise TemplateNotFound(template)
+        elif piece and piece != '.':
+            pieces.append(piece)
+    return pieces
+
+
+class BaseLoader(object):
+    """Baseclass for all loaders.  Subclass this and override `get_source` to
+    implement a custom loading mechanism.  The environment provides a
+    `get_template` method that calls the loader's `load` method to get the
+    :class:`Template` object.
+
+    A very basic example for a loader that looks up templates on the file
+    system could look like this::
+
+        from ambari_jinja2 import BaseLoader, TemplateNotFound
+        from os.path import join, exists, getmtime
+
+        class MyLoader(BaseLoader):
+
+            def __init__(self, path):
+                self.path = path
+
+            def get_source(self, environment, template):
+                path = join(self.path, template)
+                if not exists(path):
+                    raise TemplateNotFound(template)
+                mtime = getmtime(path)
+                with file(path) as f:
+                    source = f.read().decode('utf-8')
+                return source, path, lambda: mtime == getmtime(path)
+    """
+
+    #: if set to `False` it indicates that the loader cannot provide access
+    #: to the source of templates.
+    #:
+    #: .. versionadded:: 2.4
+    has_source_access = True
+
+    def get_source(self, environment, template):
+        """Get the template source, filename and reload helper for a template.
+        It's passed the environment and template name and has to return a
+        tuple in the form ``(source, filename, uptodate)`` or raise a
+        `TemplateNotFound` error if it can't locate the template.
+
+        The source part of the returned tuple must be the source of the
+        template as unicode string or a ASCII bytestring.  The filename should
+        be the name of the file on the filesystem if it was loaded from there,
+        otherwise `None`.  The filename is used by python for the tracebacks
+        if no loader extension is used.
+
+        The last item in the tuple is the `uptodate` function.  If auto
+        reloading is enabled it's always called to check if the template
+        changed.  No arguments are passed so the function must store the
+        old state somewhere (for example in a closure).  If it returns `False`
+        the template will be reloaded.
+        """
+        if not self.has_source_access:
+            raise RuntimeError('%s cannot provide access to the source' %
+                               self.__class__.__name__)
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        """Iterates over all templates.  If the loader does not support that
+        it should raise a :exc:`TypeError` which is the default behavior.
+        """
+        raise TypeError('this loader cannot iterate over all templates')
+
+    @internalcode
+    def load(self, environment, name, globals=None):
+        """Loads a template.  This method looks up the template in the cache
+        or loads one by calling :meth:`get_source`.  Subclasses should not
+        override this method as loaders working on collections of other
+        loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)
+        will not call this method but `get_source` directly.
+        """
+        code = None
+        if globals is None:
+            globals = {}
+
+        # first we try to get the source for this template together
+        # with the filename and the uptodate function.
+        source, filename, uptodate = self.get_source(environment, name)
+
+        # try to load the code from the bytecode cache if there is a
+        # bytecode cache configured.
+        bcc = environment.bytecode_cache
+        if bcc is not None:
+            bucket = bcc.get_bucket(environment, name, filename, source)
+            code = bucket.code
+
+        # if we don't have code so far (not cached, no longer up to
+        # date) etc. we compile the template
+        if code is None:
+            code = environment.compile(source, name, filename)
+
+        # if the bytecode cache is available and the bucket doesn't
+        # have a code so far, we give the bucket the new code and put
+        # it back to the bytecode cache.
+        if bcc is not None and bucket.code is None:
+            bucket.code = code
+            bcc.set_bucket(bucket)
+
+        return environment.template_class.from_code(environment, code,
+                                                    globals, uptodate)
+
+
+class FileSystemLoader(BaseLoader):
+    """Loads templates from the file system.  This loader can find templates
+    in folders on the file system and is the preferred way to load them.
+
+    The loader takes the path to the templates as string, or if multiple
+    locations are wanted a list of them which is then looked up in the
+    given order:
+
+    >>> loader = FileSystemLoader('/path/to/templates')
+    >>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
+
+    Per default the template encoding is ``'utf-8'`` which can be changed
+    by setting the `encoding` parameter to something else.
+    """
+
+    def __init__(self, searchpath, encoding='utf-8'):
+        if isinstance(searchpath, basestring):
+            searchpath = [searchpath]
+        self.searchpath = list(searchpath)
+        self.encoding = encoding
+
+    def get_source(self, environment, template):
+        pieces = split_template_path(template)
+        for searchpath in self.searchpath:
+            filename = path.join(searchpath, *pieces)
+            f = open_if_exists(filename)
+            if f is None:
+                continue
+            try:
+                contents = f.read().decode(self.encoding)
+            finally:
+                f.close()
+
+            mtime = path.getmtime(filename)
+            def uptodate():
+                try:
+                    return path.getmtime(filename) == mtime
+                except OSError:
+                    return False
+            return contents, filename, uptodate
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        found = set()
+        for searchpath in self.searchpath:
+            for dirpath, dirnames, filenames in os.walk(searchpath):
+                for filename in filenames:
+                    template = os.path.join(dirpath, filename) \
+                        [len(searchpath):].strip(os.path.sep) \
+                                          .replace(os.path.sep, '/')
+                    if template[:2] == './':
+                        template = template[2:]
+                    if template not in found:
+                        found.add(template)
+        return sorted(found)
+
+
+class PackageLoader(BaseLoader):
+    """Load templates from python eggs or packages.  It is constructed with
+    the name of the python package and the path to the templates in that
+    package::
+
+        loader = PackageLoader('mypackage', 'views')
+
+    If the package path is not given, ``'templates'`` is assumed.
+
+    Per default the template encoding is ``'utf-8'`` which can be changed
+    by setting the `encoding` parameter to something else.  Due to the nature
+    of eggs it's only possible to reload templates if the package was loaded
+    from the file system and not a zip file.
+    """
+
+    def __init__(self, package_name, package_path='templates',
+                 encoding='utf-8'):
+        from pkg_resources import DefaultProvider, ResourceManager, \
+                                  get_provider
+        provider = get_provider(package_name)
+        self.encoding = encoding
+        self.manager = ResourceManager()
+        self.filesystem_bound = isinstance(provider, DefaultProvider)
+        self.provider = provider
+        self.package_path = package_path
+
+    def get_source(self, environment, template):
+        pieces = split_template_path(template)
+        p = '/'.join((self.package_path,) + tuple(pieces))
+        if not self.provider.has_resource(p):
+            raise TemplateNotFound(template)
+
+        filename = uptodate = None
+        if self.filesystem_bound:
+            filename = self.provider.get_resource_filename(self.manager, p)
+            mtime = path.getmtime(filename)
+            def uptodate():
+                try:
+                    return path.getmtime(filename) == mtime
+                except OSError:
+                    return False
+
+        source = self.provider.get_resource_string(self.manager, p)
+        return source.decode(self.encoding), filename, uptodate
+
+    def list_templates(self):
+        path = self.package_path
+        if path[:2] == './':
+            path = path[2:]
+        elif path == '.':
+            path = ''
+        offset = len(path)
+        results = []
+        def _walk(path):
+            for filename in self.provider.resource_listdir(path):
+                fullname = path + '/' + filename
+                if self.provider.resource_isdir(fullname):
+                    for item in _walk(fullname):
+                        results.append(item)
+                else:
+                    results.append(fullname[offset:].lstrip('/'))
+        _walk(path)
+        results.sort()
+        return results
+
+
+class DictLoader(BaseLoader):
+    """Loads a template from a python dict.  It's passed a dict of unicode
+    strings bound to template names.  This loader is useful for unittesting:
+
+    >>> loader = DictLoader({'index.html': 'source here'})
+
+    Because auto reloading is rarely useful this is disabled per default.
+    """
+
+    def __init__(self, mapping):
+        self.mapping = mapping
+
+    def get_source(self, environment, template):
+        if template in self.mapping:
+            source = self.mapping[template]
+            return source, None, lambda: source != self.mapping.get(template)
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        return sorted(self.mapping)
+
+
+class FunctionLoader(BaseLoader):
+    """A loader that is passed a function which does the loading.  The
+    function becomes the name of the template passed and has to return either
+    an unicode string with the template source, a tuple in the form ``(source,
+    filename, uptodatefunc)`` or `None` if the template does not exist.
+
+    >>> def load_template(name):
+    ...     if name == 'index.html':
+    ...         return '...'
+    ...
+    >>> loader = FunctionLoader(load_template)
+
+    The `uptodatefunc` is a function that is called if autoreload is enabled
+    and has to return `True` if the template is still up to date.  For more
+    details have a look at :meth:`BaseLoader.get_source` which has the same
+    return value.
+    """
+
+    def __init__(self, load_func):
+        self.load_func = load_func
+
+    def get_source(self, environment, template):
+        rv = self.load_func(template)
+        if rv is None:
+            raise TemplateNotFound(template)
+        elif isinstance(rv, basestring):
+            return rv, None, None
+        return rv
+
+
+class PrefixLoader(BaseLoader):
+    """A loader that is passed a dict of loaders where each loader is bound
+    to a prefix.  The prefix is delimited from the template by a slash per
+    default, which can be changed by setting the `delimiter` argument to
+    something else::
+
+        loader = PrefixLoader({
+            'app1':     PackageLoader('mypackage.app1'),
+            'app2':     PackageLoader('mypackage.app2')
+        })
+
+    By loading ``'app1/index.html'`` the file from the app1 package is loaded,
+    by loading ``'app2/index.html'`` the file from the second.
+    """
+
+    def __init__(self, mapping, delimiter='/'):
+        self.mapping = mapping
+        self.delimiter = delimiter
+
+    def get_source(self, environment, template):
+        try:
+            prefix, name = template.split(self.delimiter, 1)
+            loader = self.mapping[prefix]
+        except (ValueError, KeyError):
+            raise TemplateNotFound(template)
+        try:
+            return loader.get_source(environment, name)
+        except TemplateNotFound:
+            # re-raise the exception with the correct fileame here.
+            # (the one that includes the prefix)
+            raise TemplateNotFound(template)
+
+    def list_templates(self):
+        result = []
+        for prefix, loader in self.mapping.iteritems():
+            for template in loader.list_templates():
+                result.append(prefix + self.delimiter + template)
+        return result
+
+
+class ChoiceLoader(BaseLoader):
+    """This loader works like the `PrefixLoader` just that no prefix is
+    specified.  If a template could not be found by one loader the next one
+    is tried.
+
+    >>> loader = ChoiceLoader([
+    ...     FileSystemLoader('/path/to/user/templates'),
+    ...     FileSystemLoader('/path/to/system/templates')
+    ... ])
+
+    This is useful if you want to allow users to override builtin templates
+    from a different location.
+    """
+
+    def __init__(self, loaders):
+        self.loaders = loaders
+
+    def get_source(self, environment, template):
+        for loader in self.loaders:
+            try:
+                return loader.get_source(environment, template)
+            except TemplateNotFound:
+                pass
+        raise TemplateNotFound(template)
+
+    def list_templates(self):
+        found = set()
+        for loader in self.loaders:
+            found.update(loader.list_templates())
+        return sorted(found)
+
+
+class _TemplateModule(ModuleType):
+    """Like a normal module but with support for weak references"""
+
+
+class ModuleLoader(BaseLoader):
+    """This loader loads templates from precompiled templates.
+
+    Example usage:
+
+    >>> loader = ChoiceLoader([
+    ...     ModuleLoader('/path/to/compiled/templates'),
+    ...     FileSystemLoader('/path/to/templates')
+    ... ])
+    """
+
+    has_source_access = False
+
+    def __init__(self, path):
+        package_name = '_ambari_jinja2_module_templates_%x' % id(self)
+
+        # create a fake module that looks for the templates in the
+        # path given.
+        mod = _TemplateModule(package_name)
+        if isinstance(path, basestring):
+            path = [path]
+        else:
+            path = list(path)
+        mod.__path__ = path
+
+        sys.modules[package_name] = weakref.proxy(mod,
+            lambda x: sys.modules.pop(package_name, None))
+
+        # the only strong reference, the sys.modules entry is weak
+        # so that the garbage collector can remove it once the
+        # loader that created it goes out of business.
+        self.module = mod
+        self.package_name = package_name
+
+    @staticmethod
+    def get_template_key(name):
+        return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest()
+
+    @staticmethod
+    def get_module_filename(name):
+        return ModuleLoader.get_template_key(name) + '.py'
+
+    @internalcode
+    def load(self, environment, name, globals=None):
+        key = self.get_template_key(name)
+        module = '%s.%s' % (self.package_name, key)
+        mod = getattr(self.module, module, None)
+        if mod is None:
+            try:
+                mod = __import__(module, None, None, ['root'])
+            except ImportError:
+                raise TemplateNotFound(name)
+
+            # remove the entry from sys.modules, we only want the attribute
+            # on the module object we have stored on the loader.
+            sys.modules.pop(module, None)
+
+        return environment.template_class.from_module_dict(
+            environment, mod.__dict__, globals)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py
new file mode 100644
index 0000000..afe7771
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/meta.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.meta
+    ~~~~~~~~~~~
+
+    This module implements various functions that exposes information about
+    templates that might be interesting for various kinds of applications.
+
+    :copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details.
+    :license: BSD, see LICENSE for more details.
+"""
+from ambari_jinja2 import nodes
+from ambari_jinja2.compiler import CodeGenerator
+
+
+class TrackingCodeGenerator(CodeGenerator):
+    """We abuse the code generator for introspection."""
+
+    def __init__(self, environment):
+        CodeGenerator.__init__(self, environment, '<introspection>',
+                               '<introspection>')
+        self.undeclared_identifiers = set()
+
+    def write(self, x):
+        """Don't write."""
+
+    def pull_locals(self, frame):
+        """Remember all undeclared identifiers."""
+        self.undeclared_identifiers.update(frame.identifiers.undeclared)
+
+
+def find_undeclared_variables(ast):
+    """Returns a set of all variables in the AST that will be looked up from
+    the context at runtime.  Because at compile time it's not known which
+    variables will be used depending on the path the execution takes at
+    runtime, all variables are returned.
+
+    >>> from ambari_jinja2 import Environment, meta
+    >>> env = Environment()
+    >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+    >>> meta.find_undeclared_variables(ast)
+    set(['bar'])
+
+    .. admonition:: Implementation
+
+       Internally the code generator is used for finding undeclared variables.
+       This is good to know because the code generator might raise a
+       :exc:`TemplateAssertionError` during compilation and as a matter of
+       fact this function can currently raise that exception as well.
+    """
+    codegen = TrackingCodeGenerator(ast.environment)
+    codegen.visit(ast)
+    return codegen.undeclared_identifiers
+
+
+def find_referenced_templates(ast):
+    """Finds all the referenced templates from the AST.  This will return an
+    iterator over all the hardcoded template extensions, inclusions and
+    imports.  If dynamic inheritance or inclusion is used, `None` will be
+    yielded.
+
+    >>> from ambari_jinja2 import Environment, meta
+    >>> env = Environment()
+    >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+    >>> list(meta.find_referenced_templates(ast))
+    ['layout.html', None]
+
+    This function is useful for dependency tracking.  For example if you want
+    to rebuild parts of the website after a layout template has changed.
+    """
+    for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import,
+                              nodes.Include)):
+        if not isinstance(node.template, nodes.Const):
+            # a tuple with some non consts in there
+            if isinstance(node.template, (nodes.Tuple, nodes.List)):
+                for template_name in node.template.items:
+                    # something const, only yield the strings and ignore
+                    # non-string consts that really just make no sense
+                    if isinstance(template_name, nodes.Const):
+                        if isinstance(template_name.value, basestring):
+                            yield template_name.value
+                    # something dynamic in there
+                    else:
+                        yield None
+            # something dynamic we don't know about here
+            else:
+                yield None
+            continue
+        # constant is a basestring, direct template name
+        if isinstance(node.template.value, basestring):
+            yield node.template.value
+        # a tuple or list (latter *should* not happen) made of consts,
+        # yield the consts that are strings.  We could warn here for
+        # non string values
+        elif isinstance(node, nodes.Include) and \
+             isinstance(node.template.value, (tuple, list)):
+            for template_name in node.template.value:
+                if isinstance(template_name, basestring):
+                    yield template_name
+        # something else we don't care about, we could warn here
+        else:
+            yield None


[23/59] [abbrv] git commit: AMBARI-7139. kerberos security wizard: JS error thrown while deleting ATS host component. (jaimin)

Posted by nc...@apache.org.
AMBARI-7139. kerberos security wizard: JS error thrown while deleting ATS host component. (jaimin)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/24dea68d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/24dea68d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/24dea68d

Branch: refs/heads/branch-alerts-dev
Commit: 24dea68d6e6ec6825805b23abbc254bc61a6e351
Parents: 570de22
Author: Jaimin Jetly <ja...@hortonworks.com>
Authored: Wed Sep 3 14:34:41 2014 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Wed Sep 3 14:34:50 2014 -0700

----------------------------------------------------------------------
 ambari-web/app/controllers/main/admin/security/add/step4.js    | 3 +++
 .../main/admin/security/security_progress_controller.js        | 6 +++++-
 2 files changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/24dea68d/ambari-web/app/controllers/main/admin/security/add/step4.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/security/add/step4.js b/ambari-web/app/controllers/main/admin/security/add/step4.js
index 939647d..da599a4 100644
--- a/ambari-web/app/controllers/main/admin/security/add/step4.js
+++ b/ambari-web/app/controllers/main/admin/security/add/step4.js
@@ -179,7 +179,10 @@ App.MainAdminSecurityAddStep4Controller = App.MainAdminSecurityProgressControlle
    * callback on failed deletion of component
    */
   onDeleteError: function () {
+    var deleteAtsCommand = this.get('commands').findProperty('name', 'DELETE_ATS');
     console.warn('Error: Can\'t delete APP_TIMELINE_SERVER');
+    deleteAtsCommand.set('isError', true);
+    deleteAtsCommand.set('isSuccess', false);
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/24dea68d/ambari-web/app/controllers/main/admin/security/security_progress_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/security/security_progress_controller.js b/ambari-web/app/controllers/main/admin/security/security_progress_controller.js
index 4af298a..33c3208 100644
--- a/ambari-web/app/controllers/main/admin/security/security_progress_controller.js
+++ b/ambari-web/app/controllers/main/admin/security/security_progress_controller.js
@@ -171,7 +171,11 @@ App.MainAdminSecurityProgressController = Em.Controller.extend({
             command.set('isSuccess', true);
           } else {
             var timeLineServer = App.HostComponent.find().findProperty('componentName', 'APP_TIMELINE_SERVER');
-            this.deleteComponents('APP_TIMELINE_SERVER', timeLineServer.get('hostName'));
+            if (timeLineServer) {
+              this.deleteComponents('APP_TIMELINE_SERVER', timeLineServer.get('hostName'));
+            } else {
+              this.onDeleteComplete();
+            }
           }
         }
         return true;


[07/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py b/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py
new file mode 100644
index 0000000..1161b7f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2._stringdefs
+    ~~~~~~~~~~~~~~~~~~
+
+    Strings of all Unicode characters of a certain category.
+    Used for matching in Unicode-aware languages. Run to regenerate.
+
+    Inspired by chartypes_create.py from the MoinMoin project, original
+    implementation from Pygments.
+
+    :copyright: Copyright 2006-2009 by the Jinja team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
+
+Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb'
+
+Cn = u'\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0370\u0371\u0372\u0373\u0376\u0377\u0378\u0379\u037b\u037c\u037d\u037f\u0380\u0381\u0382\u0383\u038b\u038d\u03a2\u03cf\u0487\u04cf\u04fa\u04fb\u04fc\u04fd\u04fe\u04ff\u0510\u0511\u0512\u0513\u0514\u0515\u0516\u0517\u0518\u0519\u051a\u051b\u051c\u051d\u051e\u051f\u0520\u0521\u0522\u0523\u0524\u0525\u0526\u0527\u0528\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0557\u0558\u0560\u0588\u058b\u058c\u058d\u058e\u058f\u0590\u05ba\u05c8\u05c9\u05ca\u05cb\u05cc\u05cd\u05ce\u05cf\u05eb\u05ec\u05ed\u05ee\u05ef\u05f5\u05f6\u05f7\u05f8\u05f9\u05fa\u05fb\u05fc\u05fd\u05fe\u05ff\u0604\u0605\u0606\u0607\u0608\u0609\u060a\u0616\u0617\u0618\u0619\u061a\u061c\u061d\u0620\u063b\u063c\u063d\u063e\u063f\u065f\u070e\u074b\u074c\u076e\u076f\u0770\u0771\u0772\u0773\u0774\u0775\u0776\u0777\u0778\u0779\u077a\u077b\u077c\u077d\u077e\u077f\u07b2\u07b3\u07b4\u07b5\u07b6\u07b7\u07b8\u07b9\u07ba\u07bb\u07bc\u07bd\u07be
 \u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u07c7\u07c8\u07c9\u07ca\u07cb\u07cc\u07cd\u07ce\u07cf\u07d0\u07d1\u07d2\u07d3\u07d4\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07db\u07dc\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3\u07e4\u07e5\u07e6\u07e7\u07e8\u07e9\u07ea\u07eb\u07ec\u07ed\u07ee\u07ef\u07f0\u07f1\u07f2\u07f3\u07f4\u07f5\u07f6\u07f7\u07f8\u07f9\u07fa\u07fb\u07fc\u07fd\u07fe\u07ff\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u0817\u0818\u0819\u081a\u081b\u081c\u081d\u081e\u081f\u0820\u0821\u0822\u0823\u0824\u0825\u0826\u0827\u0828\u0829\u082a\u082b\u082c\u082d\u082e\u082f\u0830\u0831\u0832\u0833\u0834\u0835\u0836\u0837\u0838\u0839\u083a\u083b\u083c\u083d\u083e\u083f\u0840\u0841\u0842\u0843\u0844\u0845\u0846\u0847\u0848\u0849\u084a\u084b\u084c\u084d\u084e\u084f\u0850\u0851\u0852\u0853\u0854\u0855\u0856\u0857\u0858\u0859\u085a\u085b\u085c\u085d\u085e\u085f\u0860\u0861\u0862\u0863\u0864\
 u0865\u0866\u0867\u0868\u0869\u086a\u086b\u086c\u086d\u086e\u086f\u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087a\u087b\u087c\u087d\u087e\u087f\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0888\u0889\u088a\u088b\u088c\u088d\u088e\u088f\u0890\u0891\u0892\u0893\u0894\u0895\u0896\u0897\u0898\u0899\u089a\u089b\u089c\u089d\u089e\u089f\u08a0\u08a1\u08a2\u08a3\u08a4\u08a5\u08a6\u08a7\u08a8\u08a9\u08aa\u08ab\u08ac\u08ad\u08ae\u08af\u08b0\u08b1\u08b2\u08b3\u08b4\u08b5\u08b6\u08b7\u08b8\u08b9\u08ba\u08bb\u08bc\u08bd\u08be\u08bf\u08c0\u08c1\u08c2\u08c3\u08c4\u08c5\u08c6\u08c7\u08c8\u08c9\u08ca\u08cb\u08cc\u08cd\u08ce\u08cf\u08d0\u08d1\u08d2\u08d3\u08d4\u08d5\u08d6\u08d7\u08d8\u08d9\u08da\u08db\u08dc\u08dd\u08de\u08df\u08e0\u08e1\u08e2\u08e3\u08e4\u08e5\u08e6\u08e7\u08e8\u08e9\u08ea\u08eb\u08ec\u08ed\u08ee\u08ef\u08f0\u08f1\u08f2\u08f3\u08f4\u08f5\u08f6\u08f7\u08f8\u08f9\u08fa\u08fb\u08fc\u08fd\u08fe\u08ff\u0900\u093a\u093b\u094e\u094f\u0955\u0956\u0957\u0971\u0972\u0973\u
 0974\u0975\u0976\u0977\u0978\u0979\u097a\u097b\u097c\u097e\u097f\u0980\u0984\u098d\u098e\u0991\u0992\u09a9\u09b1\u09b3\u09b4\u09b5\u09ba\u09bb\u09c5\u09c6\u09c9\u09ca\u09cf\u09d0\u09d1\u09d2\u09d3\u09d4\u09d5\u09d6\u09d8\u09d9\u09da\u09db\u09de\u09e4\u09e5\u09fb\u09fc\u09fd\u09fe\u09ff\u0a00\u0a04\u0a0b\u0a0c\u0a0d\u0a0e\u0a11\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a\u0a3b\u0a3d\u0a43\u0a44\u0a45\u0a46\u0a49\u0a4a\u0a4e\u0a4f\u0a50\u0a51\u0a52\u0a53\u0a54\u0a55\u0a56\u0a57\u0a58\u0a5d\u0a5f\u0a60\u0a61\u0a62\u0a63\u0a64\u0a65\u0a75\u0a76\u0a77\u0a78\u0a79\u0a7a\u0a7b\u0a7c\u0a7d\u0a7e\u0a7f\u0a80\u0a84\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba\u0abb\u0ac6\u0aca\u0ace\u0acf\u0ad1\u0ad2\u0ad3\u0ad4\u0ad5\u0ad6\u0ad7\u0ad8\u0ad9\u0ada\u0adb\u0adc\u0add\u0ade\u0adf\u0ae4\u0ae5\u0af0\u0af2\u0af3\u0af4\u0af5\u0af6\u0af7\u0af8\u0af9\u0afa\u0afb\u0afc\u0afd\u0afe\u0aff\u0b00\u0b04\u0b0d\u0b0e\u0b11\u0b12\u0b29\u0b31\u0b34\u0b3a\u0b3b\u0b44\u0b45\u0b46\u0b49\u0b4a\u0b4e\u0b4f\u0b50\u0b51\u0b52\u0b53\u0
 b54\u0b55\u0b58\u0b59\u0b5a\u0b5b\u0b5e\u0b62\u0b63\u0b64\u0b65\u0b72\u0b73\u0b74\u0b75\u0b76\u0b77\u0b78\u0b79\u0b7a\u0b7b\u0b7c\u0b7d\u0b7e\u0b7f\u0b80\u0b81\u0b84\u0b8b\u0b8c\u0b8d\u0b91\u0b96\u0b97\u0b98\u0b9b\u0b9d\u0ba0\u0ba1\u0ba2\u0ba5\u0ba6\u0ba7\u0bab\u0bac\u0bad\u0bba\u0bbb\u0bbc\u0bbd\u0bc3\u0bc4\u0bc5\u0bc9\u0bce\u0bcf\u0bd0\u0bd1\u0bd2\u0bd3\u0bd4\u0bd5\u0bd6\u0bd8\u0bd9\u0bda\u0bdb\u0bdc\u0bdd\u0bde\u0bdf\u0be0\u0be1\u0be2\u0be3\u0be4\u0be5\u0bfb\u0bfc\u0bfd\u0bfe\u0bff\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a\u0c3b\u0c3c\u0c3d\u0c45\u0c49\u0c4e\u0c4f\u0c50\u0c51\u0c52\u0c53\u0c54\u0c57\u0c58\u0c59\u0c5a\u0c5b\u0c5c\u0c5d\u0c5e\u0c5f\u0c62\u0c63\u0c64\u0c65\u0c70\u0c71\u0c72\u0c73\u0c74\u0c75\u0c76\u0c77\u0c78\u0c79\u0c7a\u0c7b\u0c7c\u0c7d\u0c7e\u0c7f\u0c80\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba\u0cbb\u0cc5\u0cc9\u0cce\u0ccf\u0cd0\u0cd1\u0cd2\u0cd3\u0cd4\u0cd7\u0cd8\u0cd9\u0cda\u0cdb\u0cdc\u0cdd\u0cdf\u0ce2\u0ce3\u0ce4\u0ce5\u0cf0\u0cf1\u0cf2\u0cf3\u0cf4\u0cf5\u0c
 f6\u0cf7\u0cf8\u0cf9\u0cfa\u0cfb\u0cfc\u0cfd\u0cfe\u0cff\u0d00\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a\u0d3b\u0d3c\u0d3d\u0d44\u0d45\u0d49\u0d4e\u0d4f\u0d50\u0d51\u0d52\u0d53\u0d54\u0d55\u0d56\u0d58\u0d59\u0d5a\u0d5b\u0d5c\u0d5d\u0d5e\u0d5f\u0d62\u0d63\u0d64\u0d65\u0d70\u0d71\u0d72\u0d73\u0d74\u0d75\u0d76\u0d77\u0d78\u0d79\u0d7a\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f\u0d80\u0d81\u0d84\u0d97\u0d98\u0d99\u0db2\u0dbc\u0dbe\u0dbf\u0dc7\u0dc8\u0dc9\u0dcb\u0dcc\u0dcd\u0dce\u0dd5\u0dd7\u0de0\u0de1\u0de2\u0de3\u0de4\u0de5\u0de6\u0de7\u0de8\u0de9\u0dea\u0deb\u0dec\u0ded\u0dee\u0def\u0df0\u0df1\u0df5\u0df6\u0df7\u0df8\u0df9\u0dfa\u0dfb\u0dfc\u0dfd\u0dfe\u0dff\u0e00\u0e3b\u0e3c\u0e3d\u0e3e\u0e5c\u0e5d\u0e5e\u0e5f\u0e60\u0e61\u0e62\u0e63\u0e64\u0e65\u0e66\u0e67\u0e68\u0e69\u0e6a\u0e6b\u0e6c\u0e6d\u0e6e\u0e6f\u0e70\u0e71\u0e72\u0e73\u0e74\u0e75\u0e76\u0e77\u0e78\u0e79\u0e7a\u0e7b\u0e7c\u0e7d\u0e7e\u0e7f\u0e80\u0e83\u0e85\u0e86\u0e89\u0e8b\u0e8c\u0e8e\u0e8f\u0e90\u0e91\u0e92\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea
 8\u0ea9\u0eac\u0eba\u0ebe\u0ebf\u0ec5\u0ec7\u0ece\u0ecf\u0eda\u0edb\u0ede\u0edf\u0ee0\u0ee1\u0ee2\u0ee3\u0ee4\u0ee5\u0ee6\u0ee7\u0ee8\u0ee9\u0eea\u0eeb\u0eec\u0eed\u0eee\u0eef\u0ef0\u0ef1\u0ef2\u0ef3\u0ef4\u0ef5\u0ef6\u0ef7\u0ef8\u0ef9\u0efa\u0efb\u0efc\u0efd\u0efe\u0eff\u0f48\u0f6b\u0f6c\u0f6d\u0f6e\u0f6f\u0f70\u0f8c\u0f8d\u0f8e\u0f8f\u0f98\u0fbd\u0fcd\u0fce\u0fd2\u0fd3\u0fd4\u0fd5\u0fd6\u0fd7\u0fd8\u0fd9\u0fda\u0fdb\u0fdc\u0fdd\u0fde\u0fdf\u0fe0\u0fe1\u0fe2\u0fe3\u0fe4\u0fe5\u0fe6\u0fe7\u0fe8\u0fe9\u0fea\u0feb\u0fec\u0fed\u0fee\u0fef\u0ff0\u0ff1\u0ff2\u0ff3\u0ff4\u0ff5\u0ff6\u0ff7\u0ff8\u0ff9\u0ffa\u0ffb\u0ffc\u0ffd\u0ffe\u0fff\u1022\u1028\u102b\u1033\u1034\u1035\u103a\u103b\u103c\u103d\u103e\u103f\u105a\u105b\u105c\u105d\u105e\u105f\u1060\u1061\u1062\u1063\u1064\u1065\u1066\u1067\u1068\u1069\u106a\u106b\u106c\u106d\u106e\u106f\u1070\u1071\u1072\u1073\u1074\u1075\u1076\u1077\u1078\u1079\u107a\u107b\u107c\u107d\u107e\u107f\u1080\u1081\u1082\u1083\u1084\u1085\u1086\u1087\u1088\u1089
 \u108a\u108b\u108c\u108d\u108e\u108f\u1090\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\u109a\u109b\u109c\u109d\u109e\u109f\u10c6\u10c7\u10c8\u10c9\u10ca\u10cb\u10cc\u10cd\u10ce\u10cf\u10fd\u10fe\u10ff\u115a\u115b\u115c\u115d\u115e\u11a3\u11a4\u11a5\u11a6\u11a7\u11fa\u11fb\u11fc\u11fd\u11fe\u11ff\u1249\u124e\u124f\u1257\u1259\u125e\u125f\u1289\u128e\u128f\u12b1\u12b6\u12b7\u12bf\u12c1\u12c6\u12c7\u12d7\u1311\u1316\u1317\u135b\u135c\u135d\u135e\u137d\u137e\u137f\u139a\u139b\u139c\u139d\u139e\u139f\u13f5\u13f6\u13f7\u13f8\u13f9\u13fa\u13fb\u13fc\u13fd\u13fe\u13ff\u1400\u1677\u1678\u1679\u167a\u167b\u167c\u167d\u167e\u167f\u169d\u169e\u169f\u16f1\u16f2\u16f3\u16f4\u16f5\u16f6\u16f7\u16f8\u16f9\u16fa\u16fb\u16fc\u16fd\u16fe\u16ff\u170d\u1715\u1716\u1717\u1718\u1719\u171a\u171b\u171c\u171d\u171e\u171f\u1737\u1738\u1739\u173a\u173b\u173c\u173d\u173e\u173f\u1754\u1755\u1756\u1757\u1758\u1759\u175a\u175b\u175c\u175d\u175e\u175f\u176d\u1771\u1774\u1775\u1776\u1777\u1778\u1779\u177a\
 u177b\u177c\u177d\u177e\u177f\u17de\u17df\u17ea\u17eb\u17ec\u17ed\u17ee\u17ef\u17fa\u17fb\u17fc\u17fd\u17fe\u17ff\u180f\u181a\u181b\u181c\u181d\u181e\u181f\u1878\u1879\u187a\u187b\u187c\u187d\u187e\u187f\u18aa\u18ab\u18ac\u18ad\u18ae\u18af\u18b0\u18b1\u18b2\u18b3\u18b4\u18b5\u18b6\u18b7\u18b8\u18b9\u18ba\u18bb\u18bc\u18bd\u18be\u18bf\u18c0\u18c1\u18c2\u18c3\u18c4\u18c5\u18c6\u18c7\u18c8\u18c9\u18ca\u18cb\u18cc\u18cd\u18ce\u18cf\u18d0\u18d1\u18d2\u18d3\u18d4\u18d5\u18d6\u18d7\u18d8\u18d9\u18da\u18db\u18dc\u18dd\u18de\u18df\u18e0\u18e1\u18e2\u18e3\u18e4\u18e5\u18e6\u18e7\u18e8\u18e9\u18ea\u18eb\u18ec\u18ed\u18ee\u18ef\u18f0\u18f1\u18f2\u18f3\u18f4\u18f5\u18f6\u18f7\u18f8\u18f9\u18fa\u18fb\u18fc\u18fd\u18fe\u18ff\u191d\u191e\u191f\u192c\u192d\u192e\u192f\u193c\u193d\u193e\u193f\u1941\u1942\u1943\u196e\u196f\u1975\u1976\u1977\u1978\u1979\u197a\u197b\u197c\u197d\u197e\u197f\u19aa\u19ab\u19ac\u19ad\u19ae\u19af\u19ca\u19cb\u19cc\u19cd\u19ce\u19cf\u19da\u19db\u19dc\u19dd\u1a1c\u1a1d\u1a20\u
 1a21\u1a22\u1a23\u1a24\u1a25\u1a26\u1a27\u1a28\u1a29\u1a2a\u1a2b\u1a2c\u1a2d\u1a2e\u1a2f\u1a30\u1a31\u1a32\u1a33\u1a34\u1a35\u1a36\u1a37\u1a38\u1a39\u1a3a\u1a3b\u1a3c\u1a3d\u1a3e\u1a3f\u1a40\u1a41\u1a42\u1a43\u1a44\u1a45\u1a46\u1a47\u1a48\u1a49\u1a4a\u1a4b\u1a4c\u1a4d\u1a4e\u1a4f\u1a50\u1a51\u1a52\u1a53\u1a54\u1a55\u1a56\u1a57\u1a58\u1a59\u1a5a\u1a5b\u1a5c\u1a5d\u1a5e\u1a5f\u1a60\u1a61\u1a62\u1a63\u1a64\u1a65\u1a66\u1a67\u1a68\u1a69\u1a6a\u1a6b\u1a6c\u1a6d\u1a6e\u1a6f\u1a70\u1a71\u1a72\u1a73\u1a74\u1a75\u1a76\u1a77\u1a78\u1a79\u1a7a\u1a7b\u1a7c\u1a7d\u1a7e\u1a7f\u1a80\u1a81\u1a82\u1a83\u1a84\u1a85\u1a86\u1a87\u1a88\u1a89\u1a8a\u1a8b\u1a8c\u1a8d\u1a8e\u1a8f\u1a90\u1a91\u1a92\u1a93\u1a94\u1a95\u1a96\u1a97\u1a98\u1a99\u1a9a\u1a9b\u1a9c\u1a9d\u1a9e\u1a9f\u1aa0\u1aa1\u1aa2\u1aa3\u1aa4\u1aa5\u1aa6\u1aa7\u1aa8\u1aa9\u1aaa\u1aab\u1aac\u1aad\u1aae\u1aaf\u1ab0\u1ab1\u1ab2\u1ab3\u1ab4\u1ab5\u1ab6\u1ab7\u1ab8\u1ab9\u1aba\u1abb\u1abc\u1abd\u1abe\u1abf\u1ac0\u1ac1\u1ac2\u1ac3\u1ac4\u1ac5\u1ac6\u1
 ac7\u1ac8\u1ac9\u1aca\u1acb\u1acc\u1acd\u1ace\u1acf\u1ad0\u1ad1\u1ad2\u1ad3\u1ad4\u1ad5\u1ad6\u1ad7\u1ad8\u1ad9\u1ada\u1adb\u1adc\u1add\u1ade\u1adf\u1ae0\u1ae1\u1ae2\u1ae3\u1ae4\u1ae5\u1ae6\u1ae7\u1ae8\u1ae9\u1aea\u1aeb\u1aec\u1aed\u1aee\u1aef\u1af0\u1af1\u1af2\u1af3\u1af4\u1af5\u1af6\u1af7\u1af8\u1af9\u1afa\u1afb\u1afc\u1afd\u1afe\u1aff\u1b00\u1b01\u1b02\u1b03\u1b04\u1b05\u1b06\u1b07\u1b08\u1b09\u1b0a\u1b0b\u1b0c\u1b0d\u1b0e\u1b0f\u1b10\u1b11\u1b12\u1b13\u1b14\u1b15\u1b16\u1b17\u1b18\u1b19\u1b1a\u1b1b\u1b1c\u1b1d\u1b1e\u1b1f\u1b20\u1b21\u1b22\u1b23\u1b24\u1b25\u1b26\u1b27\u1b28\u1b29\u1b2a\u1b2b\u1b2c\u1b2d\u1b2e\u1b2f\u1b30\u1b31\u1b32\u1b33\u1b34\u1b35\u1b36\u1b37\u1b38\u1b39\u1b3a\u1b3b\u1b3c\u1b3d\u1b3e\u1b3f\u1b40\u1b41\u1b42\u1b43\u1b44\u1b45\u1b46\u1b47\u1b48\u1b49\u1b4a\u1b4b\u1b4c\u1b4d\u1b4e\u1b4f\u1b50\u1b51\u1b52\u1b53\u1b54\u1b55\u1b56\u1b57\u1b58\u1b59\u1b5a\u1b5b\u1b5c\u1b5d\u1b5e\u1b5f\u1b60\u1b61\u1b62\u1b63\u1b64\u1b65\u1b66\u1b67\u1b68\u1b69\u1b6a\u1b6b\u1b6c\u1b
 6d\u1b6e\u1b6f\u1b70\u1b71\u1b72\u1b73\u1b74\u1b75\u1b76\u1b77\u1b78\u1b79\u1b7a\u1b7b\u1b7c\u1b7d\u1b7e\u1b7f\u1b80\u1b81\u1b82\u1b83\u1b84\u1b85\u1b86\u1b87\u1b88\u1b89\u1b8a\u1b8b\u1b8c\u1b8d\u1b8e\u1b8f\u1b90\u1b91\u1b92\u1b93\u1b94\u1b95\u1b96\u1b97\u1b98\u1b99\u1b9a\u1b9b\u1b9c\u1b9d\u1b9e\u1b9f\u1ba0\u1ba1\u1ba2\u1ba3\u1ba4\u1ba5\u1ba6\u1ba7\u1ba8\u1ba9\u1baa\u1bab\u1bac\u1bad\u1bae\u1baf\u1bb0\u1bb1\u1bb2\u1bb3\u1bb4\u1bb5\u1bb6\u1bb7\u1bb8\u1bb9\u1bba\u1bbb\u1bbc\u1bbd\u1bbe\u1bbf\u1bc0\u1bc1\u1bc2\u1bc3\u1bc4\u1bc5\u1bc6\u1bc7\u1bc8\u1bc9\u1bca\u1bcb\u1bcc\u1bcd\u1bce\u1bcf\u1bd0\u1bd1\u1bd2\u1bd3\u1bd4\u1bd5\u1bd6\u1bd7\u1bd8\u1bd9\u1bda\u1bdb\u1bdc\u1bdd\u1bde\u1bdf\u1be0\u1be1\u1be2\u1be3\u1be4\u1be5\u1be6\u1be7\u1be8\u1be9\u1bea\u1beb\u1bec\u1bed\u1bee\u1bef\u1bf0\u1bf1\u1bf2\u1bf3\u1bf4\u1bf5\u1bf6\u1bf7\u1bf8\u1bf9\u1bfa\u1bfb\u1bfc\u1bfd\u1bfe\u1bff\u1c00\u1c01\u1c02\u1c03\u1c04\u1c05\u1c06\u1c07\u1c08\u1c09\u1c0a\u1c0b\u1c0c\u1c0d\u1c0e\u1c0f\u1c10\u1c11\u1c12\u1c1
 3\u1c14\u1c15\u1c16\u1c17\u1c18\u1c19\u1c1a\u1c1b\u1c1c\u1c1d\u1c1e\u1c1f\u1c20\u1c21\u1c22\u1c23\u1c24\u1c25\u1c26\u1c27\u1c28\u1c29\u1c2a\u1c2b\u1c2c\u1c2d\u1c2e\u1c2f\u1c30\u1c31\u1c32\u1c33\u1c34\u1c35\u1c36\u1c37\u1c38\u1c39\u1c3a\u1c3b\u1c3c\u1c3d\u1c3e\u1c3f\u1c40\u1c41\u1c42\u1c43\u1c44\u1c45\u1c46\u1c47\u1c48\u1c49\u1c4a\u1c4b\u1c4c\u1c4d\u1c4e\u1c4f\u1c50\u1c51\u1c52\u1c53\u1c54\u1c55\u1c56\u1c57\u1c58\u1c59\u1c5a\u1c5b\u1c5c\u1c5d\u1c5e\u1c5f\u1c60\u1c61\u1c62\u1c63\u1c64\u1c65\u1c66\u1c67\u1c68\u1c69\u1c6a\u1c6b\u1c6c\u1c6d\u1c6e\u1c6f\u1c70\u1c71\u1c72\u1c73\u1c74\u1c75\u1c76\u1c77\u1c78\u1c79\u1c7a\u1c7b\u1c7c\u1c7d\u1c7e\u1c7f\u1c80\u1c81\u1c82\u1c83\u1c84\u1c85\u1c86\u1c87\u1c88\u1c89\u1c8a\u1c8b\u1c8c\u1c8d\u1c8e\u1c8f\u1c90\u1c91\u1c92\u1c93\u1c94\u1c95\u1c96\u1c97\u1c98\u1c99\u1c9a\u1c9b\u1c9c\u1c9d\u1c9e\u1c9f\u1ca0\u1ca1\u1ca2\u1ca3\u1ca4\u1ca5\u1ca6\u1ca7\u1ca8\u1ca9\u1caa\u1cab\u1cac\u1cad\u1cae\u1caf\u1cb0\u1cb1\u1cb2\u1cb3\u1cb4\u1cb5\u1cb6\u1cb7\u1cb8\u1cb9
 \u1cba\u1cbb\u1cbc\u1cbd\u1cbe\u1cbf\u1cc0\u1cc1\u1cc2\u1cc3\u1cc4\u1cc5\u1cc6\u1cc7\u1cc8\u1cc9\u1cca\u1ccb\u1ccc\u1ccd\u1cce\u1ccf\u1cd0\u1cd1\u1cd2\u1cd3\u1cd4\u1cd5\u1cd6\u1cd7\u1cd8\u1cd9\u1cda\u1cdb\u1cdc\u1cdd\u1cde\u1cdf\u1ce0\u1ce1\u1ce2\u1ce3\u1ce4\u1ce5\u1ce6\u1ce7\u1ce8\u1ce9\u1cea\u1ceb\u1cec\u1ced\u1cee\u1cef\u1cf0\u1cf1\u1cf2\u1cf3\u1cf4\u1cf5\u1cf6\u1cf7\u1cf8\u1cf9\u1cfa\u1cfb\u1cfc\u1cfd\u1cfe\u1cff\u1dc4\u1dc5\u1dc6\u1dc7\u1dc8\u1dc9\u1dca\u1dcb\u1dcc\u1dcd\u1dce\u1dcf\u1dd0\u1dd1\u1dd2\u1dd3\u1dd4\u1dd5\u1dd6\u1dd7\u1dd8\u1dd9\u1dda\u1ddb\u1ddc\u1ddd\u1dde\u1ddf\u1de0\u1de1\u1de2\u1de3\u1de4\u1de5\u1de6\u1de7\u1de8\u1de9\u1dea\u1deb\u1dec\u1ded\u1dee\u1def\u1df0\u1df1\u1df2\u1df3\u1df4\u1df5\u1df6\u1df7\u1df8\u1df9\u1dfa\u1dfb\u1dfc\u1dfd\u1dfe\u1dff\u1e9c\u1e9d\u1e9e\u1e9f\u1efa\u1efb\u1efc\u1efd\u1efe\u1eff\u1f16\u1f17\u1f1e\u1f1f\u1f46\u1f47\u1f4e\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e\u1f7f\u1fb5\u1fc5\u1fd4\u1fd5\u1fdc\u1ff0\u1ff1\u1ff5\u1fff\u2064\u2065\u2066\
 u2067\u2068\u2069\u2072\u2073\u208f\u2095\u2096\u2097\u2098\u2099\u209a\u209b\u209c\u209d\u209e\u209f\u20b6\u20b7\u20b8\u20b9\u20ba\u20bb\u20bc\u20bd\u20be\u20bf\u20c0\u20c1\u20c2\u20c3\u20c4\u20c5\u20c6\u20c7\u20c8\u20c9\u20ca\u20cb\u20cc\u20cd\u20ce\u20cf\u20ec\u20ed\u20ee\u20ef\u20f0\u20f1\u20f2\u20f3\u20f4\u20f5\u20f6\u20f7\u20f8\u20f9\u20fa\u20fb\u20fc\u20fd\u20fe\u20ff\u214d\u214e\u214f\u2150\u2151\u2152\u2184\u2185\u2186\u2187\u2188\u2189\u218a\u218b\u218c\u218d\u218e\u218f\u23dc\u23dd\u23de\u23df\u23e0\u23e1\u23e2\u23e3\u23e4\u23e5\u23e6\u23e7\u23e8\u23e9\u23ea\u23eb\u23ec\u23ed\u23ee\u23ef\u23f0\u23f1\u23f2\u23f3\u23f4\u23f5\u23f6\u23f7\u23f8\u23f9\u23fa\u23fb\u23fc\u23fd\u23fe\u23ff\u2427\u2428\u2429\u242a\u242b\u242c\u242d\u242e\u242f\u2430\u2431\u2432\u2433\u2434\u2435\u2436\u2437\u2438\u2439\u243a\u243b\u243c\u243d\u243e\u243f\u244b\u244c\u244d\u244e\u244f\u2450\u2451\u2452\u2453\u2454\u2455\u2456\u2457\u2458\u2459\u245a\u245b\u245c\u245d\u245e\u245f\u269d\u269e\u269f\u
 26b2\u26b3\u26b4\u26b5\u26b6\u26b7\u26b8\u26b9\u26ba\u26bb\u26bc\u26bd\u26be\u26bf\u26c0\u26c1\u26c2\u26c3\u26c4\u26c5\u26c6\u26c7\u26c8\u26c9\u26ca\u26cb\u26cc\u26cd\u26ce\u26cf\u26d0\u26d1\u26d2\u26d3\u26d4\u26d5\u26d6\u26d7\u26d8\u26d9\u26da\u26db\u26dc\u26dd\u26de\u26df\u26e0\u26e1\u26e2\u26e3\u26e4\u26e5\u26e6\u26e7\u26e8\u26e9\u26ea\u26eb\u26ec\u26ed\u26ee\u26ef\u26f0\u26f1\u26f2\u26f3\u26f4\u26f5\u26f6\u26f7\u26f8\u26f9\u26fa\u26fb\u26fc\u26fd\u26fe\u26ff\u2700\u2705\u270a\u270b\u2728\u274c\u274e\u2753\u2754\u2755\u2757\u275f\u2760\u2795\u2796\u2797\u27b0\u27bf\u27c7\u27c8\u27c9\u27ca\u27cb\u27cc\u27cd\u27ce\u27cf\u27ec\u27ed\u27ee\u27ef\u2b14\u2b15\u2b16\u2b17\u2b18\u2b19\u2b1a\u2b1b\u2b1c\u2b1d\u2b1e\u2b1f\u2b20\u2b21\u2b22\u2b23\u2b24\u2b25\u2b26\u2b27\u2b28\u2b29\u2b2a\u2b2b\u2b2c\u2b2d\u2b2e\u2b2f\u2b30\u2b31\u2b32\u2b33\u2b34\u2b35\u2b36\u2b37\u2b38\u2b39\u2b3a\u2b3b\u2b3c\u2b3d\u2b3e\u2b3f\u2b40\u2b41\u2b42\u2b43\u2b44\u2b45\u2b46\u2b47\u2b48\u2b49\u2b4a\u2b4b\u2b4c\u2
 b4d\u2b4e\u2b4f\u2b50\u2b51\u2b52\u2b53\u2b54\u2b55\u2b56\u2b57\u2b58\u2b59\u2b5a\u2b5b\u2b5c\u2b5d\u2b5e\u2b5f\u2b60\u2b61\u2b62\u2b63\u2b64\u2b65\u2b66\u2b67\u2b68\u2b69\u2b6a\u2b6b\u2b6c\u2b6d\u2b6e\u2b6f\u2b70\u2b71\u2b72\u2b73\u2b74\u2b75\u2b76\u2b77\u2b78\u2b79\u2b7a\u2b7b\u2b7c\u2b7d\u2b7e\u2b7f\u2b80\u2b81\u2b82\u2b83\u2b84\u2b85\u2b86\u2b87\u2b88\u2b89\u2b8a\u2b8b\u2b8c\u2b8d\u2b8e\u2b8f\u2b90\u2b91\u2b92\u2b93\u2b94\u2b95\u2b96\u2b97\u2b98\u2b99\u2b9a\u2b9b\u2b9c\u2b9d\u2b9e\u2b9f\u2ba0\u2ba1\u2ba2\u2ba3\u2ba4\u2ba5\u2ba6\u2ba7\u2ba8\u2ba9\u2baa\u2bab\u2bac\u2bad\u2bae\u2baf\u2bb0\u2bb1\u2bb2\u2bb3\u2bb4\u2bb5\u2bb6\u2bb7\u2bb8\u2bb9\u2bba\u2bbb\u2bbc\u2bbd\u2bbe\u2bbf\u2bc0\u2bc1\u2bc2\u2bc3\u2bc4\u2bc5\u2bc6\u2bc7\u2bc8\u2bc9\u2bca\u2bcb\u2bcc\u2bcd\u2bce\u2bcf\u2bd0\u2bd1\u2bd2\u2bd3\u2bd4\u2bd5\u2bd6\u2bd7\u2bd8\u2bd9\u2bda\u2bdb\u2bdc\u2bdd\u2bde\u2bdf\u2be0\u2be1\u2be2\u2be3\u2be4\u2be5\u2be6\u2be7\u2be8\u2be9\u2bea\u2beb\u2bec\u2bed\u2bee\u2bef\u2bf0\u2bf1\u2bf2\u2b
 f3\u2bf4\u2bf5\u2bf6\u2bf7\u2bf8\u2bf9\u2bfa\u2bfb\u2bfc\u2bfd\u2bfe\u2bff\u2c2f\u2c5f\u2c60\u2c61\u2c62\u2c63\u2c64\u2c65\u2c66\u2c67\u2c68\u2c69\u2c6a\u2c6b\u2c6c\u2c6d\u2c6e\u2c6f\u2c70\u2c71\u2c72\u2c73\u2c74\u2c75\u2c76\u2c77\u2c78\u2c79\u2c7a\u2c7b\u2c7c\u2c7d\u2c7e\u2c7f\u2ceb\u2cec\u2ced\u2cee\u2cef\u2cf0\u2cf1\u2cf2\u2cf3\u2cf4\u2cf5\u2cf6\u2cf7\u2cf8\u2d26\u2d27\u2d28\u2d29\u2d2a\u2d2b\u2d2c\u2d2d\u2d2e\u2d2f\u2d66\u2d67\u2d68\u2d69\u2d6a\u2d6b\u2d6c\u2d6d\u2d6e\u2d70\u2d71\u2d72\u2d73\u2d74\u2d75\u2d76\u2d77\u2d78\u2d79\u2d7a\u2d7b\u2d7c\u2d7d\u2d7e\u2d7f\u2d97\u2d98\u2d99\u2d9a\u2d9b\u2d9c\u2d9d\u2d9e\u2d9f\u2da7\u2daf\u2db7\u2dbf\u2dc7\u2dcf\u2dd7\u2ddf\u2de0\u2de1\u2de2\u2de3\u2de4\u2de5\u2de6\u2de7\u2de8\u2de9\u2dea\u2deb\u2dec\u2ded\u2dee\u2def\u2df0\u2df1\u2df2\u2df3\u2df4\u2df5\u2df6\u2df7\u2df8\u2df9\u2dfa\u2dfb\u2dfc\u2dfd\u2dfe\u2dff\u2e18\u2e19\u2e1a\u2e1b\u2e1e\u2e1f\u2e20\u2e21\u2e22\u2e23\u2e24\u2e25\u2e26\u2e27\u2e28\u2e29\u2e2a\u2e2b\u2e2c\u2e2d\u2e2e\u2e2
 f\u2e30\u2e31\u2e32\u2e33\u2e34\u2e35\u2e36\u2e37\u2e38\u2e39\u2e3a\u2e3b\u2e3c\u2e3d\u2e3e\u2e3f\u2e40\u2e41\u2e42\u2e43\u2e44\u2e45\u2e46\u2e47\u2e48\u2e49\u2e4a\u2e4b\u2e4c\u2e4d\u2e4e\u2e4f\u2e50\u2e51\u2e52\u2e53\u2e54\u2e55\u2e56\u2e57\u2e58\u2e59\u2e5a\u2e5b\u2e5c\u2e5d\u2e5e\u2e5f\u2e60\u2e61\u2e62\u2e63\u2e64\u2e65\u2e66\u2e67\u2e68\u2e69\u2e6a\u2e6b\u2e6c\u2e6d\u2e6e\u2e6f\u2e70\u2e71\u2e72\u2e73\u2e74\u2e75\u2e76\u2e77\u2e78\u2e79\u2e7a\u2e7b\u2e7c\u2e7d\u2e7e\u2e7f\u2e9a\u2ef4\u2ef5\u2ef6\u2ef7\u2ef8\u2ef9\u2efa\u2efb\u2efc\u2efd\u2efe\u2eff\u2fd6\u2fd7\u2fd8\u2fd9\u2fda\u2fdb\u2fdc\u2fdd\u2fde\u2fdf\u2fe0\u2fe1\u2fe2\u2fe3\u2fe4\u2fe5\u2fe6\u2fe7\u2fe8\u2fe9\u2fea\u2feb\u2fec\u2fed\u2fee\u2fef\u2ffc\u2ffd\u2ffe\u2fff\u3040\u3097\u3098\u3100\u3101\u3102\u3103\u3104\u312d\u312e\u312f\u3130\u318f\u31b8\u31b9\u31ba\u31bb\u31bc\u31bd\u31be\u31bf\u31d0\u31d1\u31d2\u31d3\u31d4\u31d5\u31d6\u31d7\u31d8\u31d9\u31da\u31db\u31dc\u31dd\u31de\u31df\u31e0\u31e1\u31e2\u31e3\u31e4\u31e5
 \u31e6\u31e7\u31e8\u31e9\u31ea\u31eb\u31ec\u31ed\u31ee\u31ef\u321f\u3244\u3245\u3246\u3247\u3248\u3249\u324a\u324b\u324c\u324d\u324e\u324f\u32ff\u4db6\u4db7\u4db8\u4db9\u4dba\u4dbb\u4dbc\u4dbd\u4dbe\u4dbf\u9fbc\u9fbd\u9fbe\u9fbf\u9fc0\u9fc1\u9fc2\u9fc3\u9fc4\u9fc5\u9fc6\u9fc7\u9fc8\u9fc9\u9fca\u9fcb\u9fcc\u9fcd\u9fce\u9fcf\u9fd0\u9fd1\u9fd2\u9fd3\u9fd4\u9fd5\u9fd6\u9fd7\u9fd8\u9fd9\u9fda\u9fdb\u9fdc\u9fdd\u9fde\u9fdf\u9fe0\u9fe1\u9fe2\u9fe3\u9fe4\u9fe5\u9fe6\u9fe7\u9fe8\u9fe9\u9fea\u9feb\u9fec\u9fed\u9fee\u9fef\u9ff0\u9ff1\u9ff2\u9ff3\u9ff4\u9ff5\u9ff6\u9ff7\u9ff8\u9ff9\u9ffa\u9ffb\u9ffc\u9ffd\u9ffe\u9fff\ua48d\ua48e\ua48f\ua4c7\ua4c8\ua4c9\ua4ca\ua4cb\ua4cc\ua4cd\ua4ce\ua4cf\ua4d0\ua4d1\ua4d2\ua4d3\ua4d4\ua4d5\ua4d6\ua4d7\ua4d8\ua4d9\ua4da\ua4db\ua4dc\ua4dd\ua4de\ua4df\ua4e0\ua4e1\ua4e2\ua4e3\ua4e4\ua4e5\ua4e6\ua4e7\ua4e8\ua4e9\ua4ea\ua4eb\ua4ec\ua4ed\ua4ee\ua4ef\ua4f0\ua4f1\ua4f2\ua4f3\ua4f4\ua4f5\ua4f6\ua4f7\ua4f8\ua4f9\ua4fa\ua4fb\ua4fc\ua4fd\ua4fe\ua4ff\ua500\ua501\ua502\ua503\
 ua504\ua505\ua506\ua507\ua508\ua509\ua50a\ua50b\ua50c\ua50d\ua50e\ua50f\ua510\ua511\ua512\ua513\ua514\ua515\ua516\ua517\ua518\ua519\ua51a\ua51b\ua51c\ua51d\ua51e\ua51f\ua520\ua521\ua522\ua523\ua524\ua525\ua526\ua527\ua528\ua529\ua52a\ua52b\ua52c\ua52d\ua52e\ua52f\ua530\ua531\ua532\ua533\ua534\ua535\ua536\ua537\ua538\ua539\ua53a\ua53b\ua53c\ua53d\ua53e\ua53f\ua540\ua541\ua542\ua543\ua544\ua545\ua546\ua547\ua548\ua549\ua54a\ua54b\ua54c\ua54d\ua54e\ua54f\ua550\ua551\ua552\ua553\ua554\ua555\ua556\ua557\ua558\ua559\ua55a\ua55b\ua55c\ua55d\ua55e\ua55f\ua560\ua561\ua562\ua563\ua564\ua565\ua566\ua567\ua568\ua569\ua56a\ua56b\ua56c\ua56d\ua56e\ua56f\ua570\ua571\ua572\ua573\ua574\ua575\ua576\ua577\ua578\ua579\ua57a\ua57b\ua57c\ua57d\ua57e\ua57f\ua580\ua581\ua582\ua583\ua584\ua585\ua586\ua587\ua588\ua589\ua58a\ua58b\ua58c\ua58d\ua58e\ua58f\ua590\ua591\ua592\ua593\ua594\ua595\ua596\ua597\ua598\ua599\ua59a\ua59b\ua59c\ua59d\ua59e\ua59f\ua5a0\ua5a1\ua5a2\ua5a3\ua5a4\ua5a5\ua5a6\ua5a7\ua5a8\ua5a9\u
 a5aa\ua5ab\ua5ac\ua5ad\ua5ae\ua5af\ua5b0\ua5b1\ua5b2\ua5b3\ua5b4\ua5b5\ua5b6\ua5b7\ua5b8\ua5b9\ua5ba\ua5bb\ua5bc\ua5bd\ua5be\ua5bf\ua5c0\ua5c1\ua5c2\ua5c3\ua5c4\ua5c5\ua5c6\ua5c7\ua5c8\ua5c9\ua5ca\ua5cb\ua5cc\ua5cd\ua5ce\ua5cf\ua5d0\ua5d1\ua5d2\ua5d3\ua5d4\ua5d5\ua5d6\ua5d7\ua5d8\ua5d9\ua5da\ua5db\ua5dc\ua5dd\ua5de\ua5df\ua5e0\ua5e1\ua5e2\ua5e3\ua5e4\ua5e5\ua5e6\ua5e7\ua5e8\ua5e9\ua5ea\ua5eb\ua5ec\ua5ed\ua5ee\ua5ef\ua5f0\ua5f1\ua5f2\ua5f3\ua5f4\ua5f5\ua5f6\ua5f7\ua5f8\ua5f9\ua5fa\ua5fb\ua5fc\ua5fd\ua5fe\ua5ff\ua600\ua601\ua602\ua603\ua604\ua605\ua606\ua607\ua608\ua609\ua60a\ua60b\ua60c\ua60d\ua60e\ua60f\ua610\ua611\ua612\ua613\ua614\ua615\ua616\ua617\ua618\ua619\ua61a\ua61b\ua61c\ua61d\ua61e\ua61f\ua620\ua621\ua622\ua623\ua624\ua625\ua626\ua627\ua628\ua629\ua62a\ua62b\ua62c\ua62d\ua62e\ua62f\ua630\ua631\ua632\ua633\ua634\ua635\ua636\ua637\ua638\ua639\ua63a\ua63b\ua63c\ua63d\ua63e\ua63f\ua640\ua641\ua642\ua643\ua644\ua645\ua646\ua647\ua648\ua649\ua64a\ua64b\ua64c\ua64d\ua64e\ua64f\ua
 650\ua651\ua652\ua653\ua654\ua655\ua656\ua657\ua658\ua659\ua65a\ua65b\ua65c\ua65d\ua65e\ua65f\ua660\ua661\ua662\ua663\ua664\ua665\ua666\ua667\ua668\ua669\ua66a\ua66b\ua66c\ua66d\ua66e\ua66f\ua670\ua671\ua672\ua673\ua674\ua675\ua676\ua677\ua678\ua679\ua67a\ua67b\ua67c\ua67d\ua67e\ua67f\ua680\ua681\ua682\ua683\ua684\ua685\ua686\ua687\ua688\ua689\ua68a\ua68b\ua68c\ua68d\ua68e\ua68f\ua690\ua691\ua692\ua693\ua694\ua695\ua696\ua697\ua698\ua699\ua69a\ua69b\ua69c\ua69d\ua69e\ua69f\ua6a0\ua6a1\ua6a2\ua6a3\ua6a4\ua6a5\ua6a6\ua6a7\ua6a8\ua6a9\ua6aa\ua6ab\ua6ac\ua6ad\ua6ae\ua6af\ua6b0\ua6b1\ua6b2\ua6b3\ua6b4\ua6b5\ua6b6\ua6b7\ua6b8\ua6b9\ua6ba\ua6bb\ua6bc\ua6bd\ua6be\ua6bf\ua6c0\ua6c1\ua6c2\ua6c3\ua6c4\ua6c5\ua6c6\ua6c7\ua6c8\ua6c9\ua6ca\ua6cb\ua6cc\ua6cd\ua6ce\ua6cf\ua6d0\ua6d1\ua6d2\ua6d3\ua6d4\ua6d5\ua6d6\ua6d7\ua6d8\ua6d9\ua6da\ua6db\ua6dc\ua6dd\ua6de\ua6df\ua6e0\ua6e1\ua6e2\ua6e3\ua6e4\ua6e5\ua6e6\ua6e7\ua6e8\ua6e9\ua6ea\ua6eb\ua6ec\ua6ed\ua6ee\ua6ef\ua6f0\ua6f1\ua6f2\ua6f3\ua6f4\ua6f5\ua6
 f6\ua6f7\ua6f8\ua6f9\ua6fa\ua6fb\ua6fc\ua6fd\ua6fe\ua6ff\ua717\ua718\ua719\ua71a\ua71b\ua71c\ua71d\ua71e\ua71f\ua720\ua721\ua722\ua723\ua724\ua725\ua726\ua727\ua728\ua729\ua72a\ua72b\ua72c\ua72d\ua72e\ua72f\ua730\ua731\ua732\ua733\ua734\ua735\ua736\ua737\ua738\ua739\ua73a\ua73b\ua73c\ua73d\ua73e\ua73f\ua740\ua741\ua742\ua743\ua744\ua745\ua746\ua747\ua748\ua749\ua74a\ua74b\ua74c\ua74d\ua74e\ua74f\ua750\ua751\ua752\ua753\ua754\ua755\ua756\ua757\ua758\ua759\ua75a\ua75b\ua75c\ua75d\ua75e\ua75f\ua760\ua761\ua762\ua763\ua764\ua765\ua766\ua767\ua768\ua769\ua76a\ua76b\ua76c\ua76d\ua76e\ua76f\ua770\ua771\ua772\ua773\ua774\ua775\ua776\ua777\ua778\ua779\ua77a\ua77b\ua77c\ua77d\ua77e\ua77f\ua780\ua781\ua782\ua783\ua784\ua785\ua786\ua787\ua788\ua789\ua78a\ua78b\ua78c\ua78d\ua78e\ua78f\ua790\ua791\ua792\ua793\ua794\ua795\ua796\ua797\ua798\ua799\ua79a\ua79b\ua79c\ua79d\ua79e\ua79f\ua7a0\ua7a1\ua7a2\ua7a3\ua7a4\ua7a5\ua7a6\ua7a7\ua7a8\ua7a9\ua7aa\ua7ab\ua7ac\ua7ad\ua7ae\ua7af\ua7b0\ua7b1\ua7b2\ua7b
 3\ua7b4\ua7b5\ua7b6\ua7b7\ua7b8\ua7b9\ua7ba\ua7bb\ua7bc\ua7bd\ua7be\ua7bf\ua7c0\ua7c1\ua7c2\ua7c3\ua7c4\ua7c5\ua7c6\ua7c7\ua7c8\ua7c9\ua7ca\ua7cb\ua7cc\ua7cd\ua7ce\ua7cf\ua7d0\ua7d1\ua7d2\ua7d3\ua7d4\ua7d5\ua7d6\ua7d7\ua7d8\ua7d9\ua7da\ua7db\ua7dc\ua7dd\ua7de\ua7df\ua7e0\ua7e1\ua7e2\ua7e3\ua7e4\ua7e5\ua7e6\ua7e7\ua7e8\ua7e9\ua7ea\ua7eb\ua7ec\ua7ed\ua7ee\ua7ef\ua7f0\ua7f1\ua7f2\ua7f3\ua7f4\ua7f5\ua7f6\ua7f7\ua7f8\ua7f9\ua7fa\ua7fb\ua7fc\ua7fd\ua7fe\ua7ff\ua82c\ua82d\ua82e\ua82f\ua830\ua831\ua832\ua833\ua834\ua835\ua836\ua837\ua838\ua839\ua83a\ua83b\ua83c\ua83d\ua83e\ua83f\ua840\ua841\ua842\ua843\ua844\ua845\ua846\ua847\ua848\ua849\ua84a\ua84b\ua84c\ua84d\ua84e\ua84f\ua850\ua851\ua852\ua853\ua854\ua855\ua856\ua857\ua858\ua859\ua85a\ua85b\ua85c\ua85d\ua85e\ua85f\ua860\ua861\ua862\ua863\ua864\ua865\ua866\ua867\ua868\ua869\ua86a\ua86b\ua86c\ua86d\ua86e\ua86f\ua870\ua871\ua872\ua873\ua874\ua875\ua876\ua877\ua878\ua879\ua87a\ua87b\ua87c\ua87d\ua87e\ua87f\ua880\ua881\ua882\ua883\ua884\ua885
 \ua886\ua887\ua888\ua889\ua88a\ua88b\ua88c\ua88d\ua88e\ua88f\ua890\ua891\ua892\ua893\ua894\ua895\ua896\ua897\ua898\ua899\ua89a\ua89b\ua89c\ua89d\ua89e\ua89f\ua8a0\ua8a1\ua8a2\ua8a3\ua8a4\ua8a5\ua8a6\ua8a7\ua8a8\ua8a9\ua8aa\ua8ab\ua8ac\ua8ad\ua8ae\ua8af\ua8b0\ua8b1\ua8b2\ua8b3\ua8b4\ua8b5\ua8b6\ua8b7\ua8b8\ua8b9\ua8ba\ua8bb\ua8bc\ua8bd\ua8be\ua8bf\ua8c0\ua8c1\ua8c2\ua8c3\ua8c4\ua8c5\ua8c6\ua8c7\ua8c8\ua8c9\ua8ca\ua8cb\ua8cc\ua8cd\ua8ce\ua8cf\ua8d0\ua8d1\ua8d2\ua8d3\ua8d4\ua8d5\ua8d6\ua8d7\ua8d8\ua8d9\ua8da\ua8db\ua8dc\ua8dd\ua8de\ua8df\ua8e0\ua8e1\ua8e2\ua8e3\ua8e4\ua8e5\ua8e6\ua8e7\ua8e8\ua8e9\ua8ea\ua8eb\ua8ec\ua8ed\ua8ee\ua8ef\ua8f0\ua8f1\ua8f2\ua8f3\ua8f4\ua8f5\ua8f6\ua8f7\ua8f8\ua8f9\ua8fa\ua8fb\ua8fc\ua8fd\ua8fe\ua8ff\ua900\ua901\ua902\ua903\ua904\ua905\ua906\ua907\ua908\ua909\ua90a\ua90b\ua90c\ua90d\ua90e\ua90f\ua910\ua911\ua912\ua913\ua914\ua915\ua916\ua917\ua918\ua919\ua91a\ua91b\ua91c\ua91d\ua91e\ua91f\ua920\ua921\ua922\ua923\ua924\ua925\ua926\ua927\ua928\ua929\ua92a\ua92b\
 ua92c\ua92d\ua92e\ua92f\ua930\ua931\ua932\ua933\ua934\ua935\ua936\ua937\ua938\ua939\ua93a\ua93b\ua93c\ua93d\ua93e\ua93f\ua940\ua941\ua942\ua943\ua944\ua945\ua946\ua947\ua948\ua949\ua94a\ua94b\ua94c\ua94d\ua94e\ua94f\ua950\ua951\ua952\ua953\ua954\ua955\ua956\ua957\ua958\ua959\ua95a\ua95b\ua95c\ua95d\ua95e\ua95f\ua960\ua961\ua962\ua963\ua964\ua965\ua966\ua967\ua968\ua969\ua96a\ua96b\ua96c\ua96d\ua96e\ua96f\ua970\ua971\ua972\ua973\ua974\ua975\ua976\ua977\ua978\ua979\ua97a\ua97b\ua97c\ua97d\ua97e\ua97f\ua980\ua981\ua982\ua983\ua984\ua985\ua986\ua987\ua988\ua989\ua98a\ua98b\ua98c\ua98d\ua98e\ua98f\ua990\ua991\ua992\ua993\ua994\ua995\ua996\ua997\ua998\ua999\ua99a\ua99b\ua99c\ua99d\ua99e\ua99f\ua9a0\ua9a1\ua9a2\ua9a3\ua9a4\ua9a5\ua9a6\ua9a7\ua9a8\ua9a9\ua9aa\ua9ab\ua9ac\ua9ad\ua9ae\ua9af\ua9b0\ua9b1\ua9b2\ua9b3\ua9b4\ua9b5\ua9b6\ua9b7\ua9b8\ua9b9\ua9ba\ua9bb\ua9bc\ua9bd\ua9be\ua9bf\ua9c0\ua9c1\ua9c2\ua9c3\ua9c4\ua9c5\ua9c6\ua9c7\ua9c8\ua9c9\ua9ca\ua9cb\ua9cc\ua9cd\ua9ce\ua9cf\ua9d0\ua9d1\u
 a9d2\ua9d3\ua9d4\ua9d5\ua9d6\ua9d7\ua9d8\ua9d9\ua9da\ua9db\ua9dc\ua9dd\ua9de\ua9df\ua9e0\ua9e1\ua9e2\ua9e3\ua9e4\ua9e5\ua9e6\ua9e7\ua9e8\ua9e9\ua9ea\ua9eb\ua9ec\ua9ed\ua9ee\ua9ef\ua9f0\ua9f1\ua9f2\ua9f3\ua9f4\ua9f5\ua9f6\ua9f7\ua9f8\ua9f9\ua9fa\ua9fb\ua9fc\ua9fd\ua9fe\ua9ff\uaa00\uaa01\uaa02\uaa03\uaa04\uaa05\uaa06\uaa07\uaa08\uaa09\uaa0a\uaa0b\uaa0c\uaa0d\uaa0e\uaa0f\uaa10\uaa11\uaa12\uaa13\uaa14\uaa15\uaa16\uaa17\uaa18\uaa19\uaa1a\uaa1b\uaa1c\uaa1d\uaa1e\uaa1f\uaa20\uaa21\uaa22\uaa23\uaa24\uaa25\uaa26\uaa27\uaa28\uaa29\uaa2a\uaa2b\uaa2c\uaa2d\uaa2e\uaa2f\uaa30\uaa31\uaa32\uaa33\uaa34\uaa35\uaa36\uaa37\uaa38\uaa39\uaa3a\uaa3b\uaa3c\uaa3d\uaa3e\uaa3f\uaa40\uaa41\uaa42\uaa43\uaa44\uaa45\uaa46\uaa47\uaa48\uaa49\uaa4a\uaa4b\uaa4c\uaa4d\uaa4e\uaa4f\uaa50\uaa51\uaa52\uaa53\uaa54\uaa55\uaa56\uaa57\uaa58\uaa59\uaa5a\uaa5b\uaa5c\uaa5d\uaa5e\uaa5f\uaa60\uaa61\uaa62\uaa63\uaa64\uaa65\uaa66\uaa67\uaa68\uaa69\uaa6a\uaa6b\uaa6c\uaa6d\uaa6e\uaa6f\uaa70\uaa71\uaa72\uaa73\uaa74\uaa75\uaa76\uaa77\ua
 a78\uaa79\uaa7a\uaa7b\uaa7c\uaa7d\uaa7e\uaa7f\uaa80\uaa81\uaa82\uaa83\uaa84\uaa85\uaa86\uaa87\uaa88\uaa89\uaa8a\uaa8b\uaa8c\uaa8d\uaa8e\uaa8f\uaa90\uaa91\uaa92\uaa93\uaa94\uaa95\uaa96\uaa97\uaa98\uaa99\uaa9a\uaa9b\uaa9c\uaa9d\uaa9e\uaa9f\uaaa0\uaaa1\uaaa2\uaaa3\uaaa4\uaaa5\uaaa6\uaaa7\uaaa8\uaaa9\uaaaa\uaaab\uaaac\uaaad\uaaae\uaaaf\uaab0\uaab1\uaab2\uaab3\uaab4\uaab5\uaab6\uaab7\uaab8\uaab9\uaaba\uaabb\uaabc\uaabd\uaabe\uaabf\uaac0\uaac1\uaac2\uaac3\uaac4\uaac5\uaac6\uaac7\uaac8\uaac9\uaaca\uaacb\uaacc\uaacd\uaace\uaacf\uaad0\uaad1\uaad2\uaad3\uaad4\uaad5\uaad6\uaad7\uaad8\uaad9\uaada\uaadb\uaadc\uaadd\uaade\uaadf\uaae0\uaae1\uaae2\uaae3\uaae4\uaae5\uaae6\uaae7\uaae8\uaae9\uaaea\uaaeb\uaaec\uaaed\uaaee\uaaef\uaaf0\uaaf1\uaaf2\uaaf3\uaaf4\uaaf5\uaaf6\uaaf7\uaaf8\uaaf9\uaafa\uaafb\uaafc\uaafd\uaafe\uaaff\uab00\uab01\uab02\uab03\uab04\uab05\uab06\uab07\uab08\uab09\uab0a\uab0b\uab0c\uab0d\uab0e\uab0f\uab10\uab11\uab12\uab13\uab14\uab15\uab16\uab17\uab18\uab19\uab1a\uab1b\uab1c\uab1d\uab
 1e\uab1f\uab20\uab21\uab22\uab23\uab24\uab25\uab26\uab27\uab28\uab29\uab2a\uab2b\uab2c\uab2d\uab2e\uab2f\uab30\uab31\uab32\uab33\uab34\uab35\uab36\uab37\uab38\uab39\uab3a\uab3b\uab3c\uab3d\uab3e\uab3f\uab40\uab41\uab42\uab43\uab44\uab45\uab46\uab47\uab48\uab49\uab4a\uab4b\uab4c\uab4d\uab4e\uab4f\uab50\uab51\uab52\uab53\uab54\uab55\uab56\uab57\uab58\uab59\uab5a\uab5b\uab5c\uab5d\uab5e\uab5f\uab60\uab61\uab62\uab63\uab64\uab65\uab66\uab67\uab68\uab69\uab6a\uab6b\uab6c\uab6d\uab6e\uab6f\uab70\uab71\uab72\uab73\uab74\uab75\uab76\uab77\uab78\uab79\uab7a\uab7b\uab7c\uab7d\uab7e\uab7f\uab80\uab81\uab82\uab83\uab84\uab85\uab86\uab87\uab88\uab89\uab8a\uab8b\uab8c\uab8d\uab8e\uab8f\uab90\uab91\uab92\uab93\uab94\uab95\uab96\uab97\uab98\uab99\uab9a\uab9b\uab9c\uab9d\uab9e\uab9f\uaba0\uaba1\uaba2\uaba3\uaba4\uaba5\uaba6\uaba7\uaba8\uaba9\uabaa\uabab\uabac\uabad\uabae\uabaf\uabb0\uabb1\uabb2\uabb3\uabb4\uabb5\uabb6\uabb7\uabb8\uabb9\uabba\uabbb\uabbc\uabbd\uabbe\uabbf\uabc0\uabc1\uabc2\uabc3\uabc
 4\uabc5\uabc6\uabc7\uabc8\uabc9\uabca\uabcb\uabcc\uabcd\uabce\uabcf\uabd0\uabd1\uabd2\uabd3\uabd4\uabd5\uabd6\uabd7\uabd8\uabd9\uabda\uabdb\uabdc\uabdd\uabde\uabdf\uabe0\uabe1\uabe2\uabe3\uabe4\uabe5\uabe6\uabe7\uabe8\uabe9\uabea\uabeb\uabec\uabed\uabee\uabef\uabf0\uabf1\uabf2\uabf3\uabf4\uabf5\uabf6\uabf7\uabf8\uabf9\uabfa\uabfb\uabfc\uabfd\uabfe\uabff\ud7a4\ud7a5\ud7a6\ud7a7\ud7a8\ud7a9\ud7aa\ud7ab\ud7ac\ud7ad\ud7ae\ud7af\ud7b0\ud7b1\ud7b2\ud7b3\ud7b4\ud7b5\ud7b6\ud7b7\ud7b8\ud7b9\ud7ba\ud7bb\ud7bc\ud7bd\ud7be\ud7bf\ud7c0\ud7c1\ud7c2\ud7c3\ud7c4\ud7c5\ud7c6\ud7c7\ud7c8\ud7c9\ud7ca\ud7cb\ud7cc\ud7cd\ud7ce\ud7cf\ud7d0\ud7d1\ud7d2\ud7d3\ud7d4\ud7d5\ud7d6\ud7d7\ud7d8\ud7d9\ud7da\ud7db\ud7dc\ud7dd\ud7de\ud7df\ud7e0\ud7e1\ud7e2\ud7e3\ud7e4\ud7e5\ud7e6\ud7e7\ud7e8\ud7e9\ud7ea\ud7eb\ud7ec\ud7ed\ud7ee\ud7ef\ud7f0\ud7f1\ud7f2\ud7f3\ud7f4\ud7f5\ud7f6\ud7f7\ud7f8\ud7f9\ud7fa\ud7fb\ud7fc\ud7fd\ud7fe\ud7ff\ufa2e\ufa2f\ufa6b\ufa6c\ufa6d\ufa6e\ufa6f\ufada\ufadb\ufadc\ufadd\ufade\ufadf\ufae0\ufae1
 \ufae2\ufae3\ufae4\ufae5\ufae6\ufae7\ufae8\ufae9\ufaea\ufaeb\ufaec\ufaed\ufaee\ufaef\ufaf0\ufaf1\ufaf2\ufaf3\ufaf4\ufaf5\ufaf6\ufaf7\ufaf8\ufaf9\ufafa\ufafb\ufafc\ufafd\ufafe\ufaff\ufb07\ufb08\ufb09\ufb0a\ufb0b\ufb0c\ufb0d\ufb0e\ufb0f\ufb10\ufb11\ufb12\ufb18\ufb19\ufb1a\ufb1b\ufb1c\ufb37\ufb3d\ufb3f\ufb42\ufb45\ufbb2\ufbb3\ufbb4\ufbb5\ufbb6\ufbb7\ufbb8\ufbb9\ufbba\ufbbb\ufbbc\ufbbd\ufbbe\ufbbf\ufbc0\ufbc1\ufbc2\ufbc3\ufbc4\ufbc5\ufbc6\ufbc7\ufbc8\ufbc9\ufbca\ufbcb\ufbcc\ufbcd\ufbce\ufbcf\ufbd0\ufbd1\ufbd2\ufd40\ufd41\ufd42\ufd43\ufd44\ufd45\ufd46\ufd47\ufd48\ufd49\ufd4a\ufd4b\ufd4c\ufd4d\ufd4e\ufd4f\ufd90\ufd91\ufdc8\ufdc9\ufdca\ufdcb\ufdcc\ufdcd\ufdce\ufdcf\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea\ufdeb\ufdec\ufded\ufdee\ufdef\ufdfe\ufdff\ufe1a\ufe1b\ufe1c\ufe1d\ufe1e\ufe1f\ufe24\ufe25\ufe26\ufe27\ufe28\ufe29\ufe2a\ufe2b\ufe2c\ufe2d\ufe2e\ufe2f\ufe53\ufe67\ufe6c\
 ufe6d\ufe6e\ufe6f\ufe75\ufefd\ufefe\uff00\uffbf\uffc0\uffc1\uffc8\uffc9\uffd0\uffd1\uffd8\uffd9\uffdd\uffde\uffdf\uffe7\uffef\ufff0\ufff1\ufff2\ufff3\ufff4\ufff5\ufff6\ufff7\ufff8\ufffe'
+
+Co = u'\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009\ue00a\ue00b\ue00c\ue00d\ue00e\ue00f\ue010\ue011\ue012\ue013\ue014\ue015\ue016\ue017\ue018\ue019\ue01a\ue01b\ue01c\ue01d\ue01e\ue01f\ue020\ue021\ue022\ue023\ue024\ue025\ue026\ue027\ue028\ue029\ue02a\ue02b\ue02c\ue02d\ue02e\ue02f\ue030\ue031\ue032\ue033\ue034\ue035\ue036\ue037\ue038\ue039\ue03a\ue03b\ue03c\ue03d\ue03e\ue03f\ue040\ue041\ue042\ue043\ue044\ue045\ue046\ue047\ue048\ue049\ue04a\ue04b\ue04c\ue04d\ue04e\ue04f\ue050\ue051\ue052\ue053\ue054\ue055\ue056\ue057\ue058\ue059\ue05a\ue05b\ue05c\ue05d\ue05e\ue05f\ue060\ue061\ue062\ue063\ue064\ue065\ue066\ue067\ue068\ue069\ue06a\ue06b\ue06c\ue06d\ue06e\ue06f\ue070\ue071\ue072\ue073\ue074\ue075\ue076\ue077\ue078\ue079\ue07a\ue07b\ue07c\ue07d\ue07e\ue07f\ue080\ue081\ue082\ue083\ue084\ue085\ue086\ue087\ue088\ue089\ue08a\ue08b\ue08c\ue08d\ue08e\ue08f\ue090\ue091\ue092\ue093\ue094\ue095\ue096\ue097\ue098\ue099\ue09a\ue09b\ue09c\ue09d\ue09e\ue09f\ue0a0\ue0a1\ue0a2\ue0a3\ue0a4
 \ue0a5\ue0a6\ue0a7\ue0a8\ue0a9\ue0aa\ue0ab\ue0ac\ue0ad\ue0ae\ue0af\ue0b0\ue0b1\ue0b2\ue0b3\ue0b4\ue0b5\ue0b6\ue0b7\ue0b8\ue0b9\ue0ba\ue0bb\ue0bc\ue0bd\ue0be\ue0bf\ue0c0\ue0c1\ue0c2\ue0c3\ue0c4\ue0c5\ue0c6\ue0c7\ue0c8\ue0c9\ue0ca\ue0cb\ue0cc\ue0cd\ue0ce\ue0cf\ue0d0\ue0d1\ue0d2\ue0d3\ue0d4\ue0d5\ue0d6\ue0d7\ue0d8\ue0d9\ue0da\ue0db\ue0dc\ue0dd\ue0de\ue0df\ue0e0\ue0e1\ue0e2\ue0e3\ue0e4\ue0e5\ue0e6\ue0e7\ue0e8\ue0e9\ue0ea\ue0eb\ue0ec\ue0ed\ue0ee\ue0ef\ue0f0\ue0f1\ue0f2\ue0f3\ue0f4\ue0f5\ue0f6\ue0f7\ue0f8\ue0f9\ue0fa\ue0fb\ue0fc\ue0fd\ue0fe\ue0ff\ue100\ue101\ue102\ue103\ue104\ue105\ue106\ue107\ue108\ue109\ue10a\ue10b\ue10c\ue10d\ue10e\ue10f\ue110\ue111\ue112\ue113\ue114\ue115\ue116\ue117\ue118\ue119\ue11a\ue11b\ue11c\ue11d\ue11e\ue11f\ue120\ue121\ue122\ue123\ue124\ue125\ue126\ue127\ue128\ue129\ue12a\ue12b\ue12c\ue12d\ue12e\ue12f\ue130\ue131\ue132\ue133\ue134\ue135\ue136\ue137\ue138\ue139\ue13a\ue13b\ue13c\ue13d\ue13e\ue13f\ue140\ue141\ue142\ue143\ue144\ue145\ue146\ue147\ue148\ue149\ue14a\
 ue14b\ue14c\ue14d\ue14e\ue14f\ue150\ue151\ue152\ue153\ue154\ue155\ue156\ue157\ue158\ue159\ue15a\ue15b\ue15c\ue15d\ue15e\ue15f\ue160\ue161\ue162\ue163\ue164\ue165\ue166\ue167\ue168\ue169\ue16a\ue16b\ue16c\ue16d\ue16e\ue16f\ue170\ue171\ue172\ue173\ue174\ue175\ue176\ue177\ue178\ue179\ue17a\ue17b\ue17c\ue17d\ue17e\ue17f\ue180\ue181\ue182\ue183\ue184\ue185\ue186\ue187\ue188\ue189\ue18a\ue18b\ue18c\ue18d\ue18e\ue18f\ue190\ue191\ue192\ue193\ue194\ue195\ue196\ue197\ue198\ue199\ue19a\ue19b\ue19c\ue19d\ue19e\ue19f\ue1a0\ue1a1\ue1a2\ue1a3\ue1a4\ue1a5\ue1a6\ue1a7\ue1a8\ue1a9\ue1aa\ue1ab\ue1ac\ue1ad\ue1ae\ue1af\ue1b0\ue1b1\ue1b2\ue1b3\ue1b4\ue1b5\ue1b6\ue1b7\ue1b8\ue1b9\ue1ba\ue1bb\ue1bc\ue1bd\ue1be\ue1bf\ue1c0\ue1c1\ue1c2\ue1c3\ue1c4\ue1c5\ue1c6\ue1c7\ue1c8\ue1c9\ue1ca\ue1cb\ue1cc\ue1cd\ue1ce\ue1cf\ue1d0\ue1d1\ue1d2\ue1d3\ue1d4\ue1d5\ue1d6\ue1d7\ue1d8\ue1d9\ue1da\ue1db\ue1dc\ue1dd\ue1de\ue1df\ue1e0\ue1e1\ue1e2\ue1e3\ue1e4\ue1e5\ue1e6\ue1e7\ue1e8\ue1e9\ue1ea\ue1eb\ue1ec\ue1ed\ue1ee\ue1ef\ue1f0\u
 e1f1\ue1f2\ue1f3\ue1f4\ue1f5\ue1f6\ue1f7\ue1f8\ue1f9\ue1fa\ue1fb\ue1fc\ue1fd\ue1fe\ue1ff\ue200\ue201\ue202\ue203\ue204\ue205\ue206\ue207\ue208\ue209\ue20a\ue20b\ue20c\ue20d\ue20e\ue20f\ue210\ue211\ue212\ue213\ue214\ue215\ue216\ue217\ue218\ue219\ue21a\ue21b\ue21c\ue21d\ue21e\ue21f\ue220\ue221\ue222\ue223\ue224\ue225\ue226\ue227\ue228\ue229\ue22a\ue22b\ue22c\ue22d\ue22e\ue22f\ue230\ue231\ue232\ue233\ue234\ue235\ue236\ue237\ue238\ue239\ue23a\ue23b\ue23c\ue23d\ue23e\ue23f\ue240\ue241\ue242\ue243\ue244\ue245\ue246\ue247\ue248\ue249\ue24a\ue24b\ue24c\ue24d\ue24e\ue24f\ue250\ue251\ue252\ue253\ue254\ue255\ue256\ue257\ue258\ue259\ue25a\ue25b\ue25c\ue25d\ue25e\ue25f\ue260\ue261\ue262\ue263\ue264\ue265\ue266\ue267\ue268\ue269\ue26a\ue26b\ue26c\ue26d\ue26e\ue26f\ue270\ue271\ue272\ue273\ue274\ue275\ue276\ue277\ue278\ue279\ue27a\ue27b\ue27c\ue27d\ue27e\ue27f\ue280\ue281\ue282\ue283\ue284\ue285\ue286\ue287\ue288\ue289\ue28a\ue28b\ue28c\ue28d\ue28e\ue28f\ue290\ue291\ue292\ue293\ue294\ue295\ue296\ue
 297\ue298\ue299\ue29a\ue29b\ue29c\ue29d\ue29e\ue29f\ue2a0\ue2a1\ue2a2\ue2a3\ue2a4\ue2a5\ue2a6\ue2a7\ue2a8\ue2a9\ue2aa\ue2ab\ue2ac\ue2ad\ue2ae\ue2af\ue2b0\ue2b1\ue2b2\ue2b3\ue2b4\ue2b5\ue2b6\ue2b7\ue2b8\ue2b9\ue2ba\ue2bb\ue2bc\ue2bd\ue2be\ue2bf\ue2c0\ue2c1\ue2c2\ue2c3\ue2c4\ue2c5\ue2c6\ue2c7\ue2c8\ue2c9\ue2ca\ue2cb\ue2cc\ue2cd\ue2ce\ue2cf\ue2d0\ue2d1\ue2d2\ue2d3\ue2d4\ue2d5\ue2d6\ue2d7\ue2d8\ue2d9\ue2da\ue2db\ue2dc\ue2dd\ue2de\ue2df\ue2e0\ue2e1\ue2e2\ue2e3\ue2e4\ue2e5\ue2e6\ue2e7\ue2e8\ue2e9\ue2ea\ue2eb\ue2ec\ue2ed\ue2ee\ue2ef\ue2f0\ue2f1\ue2f2\ue2f3\ue2f4\ue2f5\ue2f6\ue2f7\ue2f8\ue2f9\ue2fa\ue2fb\ue2fc\ue2fd\ue2fe\ue2ff\ue300\ue301\ue302\ue303\ue304\ue305\ue306\ue307\ue308\ue309\ue30a\ue30b\ue30c\ue30d\ue30e\ue30f\ue310\ue311\ue312\ue313\ue314\ue315\ue316\ue317\ue318\ue319\ue31a\ue31b\ue31c\ue31d\ue31e\ue31f\ue320\ue321\ue322\ue323\ue324\ue325\ue326\ue327\ue328\ue329\ue32a\ue32b\ue32c\ue32d\ue32e\ue32f\ue330\ue331\ue332\ue333\ue334\ue335\ue336\ue337\ue338\ue339\ue33a\ue33b\ue33c\ue3
 3d\ue33e\ue33f\ue340\ue341\ue342\ue343\ue344\ue345\ue346\ue347\ue348\ue349\ue34a\ue34b\ue34c\ue34d\ue34e\ue34f\ue350\ue351\ue352\ue353\ue354\ue355\ue356\ue357\ue358\ue359\ue35a\ue35b\ue35c\ue35d\ue35e\ue35f\ue360\ue361\ue362\ue363\ue364\ue365\ue366\ue367\ue368\ue369\ue36a\ue36b\ue36c\ue36d\ue36e\ue36f\ue370\ue371\ue372\ue373\ue374\ue375\ue376\ue377\ue378\ue379\ue37a\ue37b\ue37c\ue37d\ue37e\ue37f\ue380\ue381\ue382\ue383\ue384\ue385\ue386\ue387\ue388\ue389\ue38a\ue38b\ue38c\ue38d\ue38e\ue38f\ue390\ue391\ue392\ue393\ue394\ue395\ue396\ue397\ue398\ue399\ue39a\ue39b\ue39c\ue39d\ue39e\ue39f\ue3a0\ue3a1\ue3a2\ue3a3\ue3a4\ue3a5\ue3a6\ue3a7\ue3a8\ue3a9\ue3aa\ue3ab\ue3ac\ue3ad\ue3ae\ue3af\ue3b0\ue3b1\ue3b2\ue3b3\ue3b4\ue3b5\ue3b6\ue3b7\ue3b8\ue3b9\ue3ba\ue3bb\ue3bc\ue3bd\ue3be\ue3bf\ue3c0\ue3c1\ue3c2\ue3c3\ue3c4\ue3c5\ue3c6\ue3c7\ue3c8\ue3c9\ue3ca\ue3cb\ue3cc\ue3cd\ue3ce\ue3cf\ue3d0\ue3d1\ue3d2\ue3d3\ue3d4\ue3d5\ue3d6\ue3d7\ue3d8\ue3d9\ue3da\ue3db\ue3dc\ue3dd\ue3de\ue3df\ue3e0\ue3e1\ue3e2\ue3e
 3\ue3e4\ue3e5\ue3e6\ue3e7\ue3e8\ue3e9\ue3ea\ue3eb\ue3ec\ue3ed\ue3ee\ue3ef\ue3f0\ue3f1\ue3f2\ue3f3\ue3f4\ue3f5\ue3f6\ue3f7\ue3f8\ue3f9\ue3fa\ue3fb\ue3fc\ue3fd\ue3fe\ue3ff\ue400\ue401\ue402\ue403\ue404\ue405\ue406\ue407\ue408\ue409\ue40a\ue40b\ue40c\ue40d\ue40e\ue40f\ue410\ue411\ue412\ue413\ue414\ue415\ue416\ue417\ue418\ue419\ue41a\ue41b\ue41c\ue41d\ue41e\ue41f\ue420\ue421\ue422\ue423\ue424\ue425\ue426\ue427\ue428\ue429\ue42a\ue42b\ue42c\ue42d\ue42e\ue42f\ue430\ue431\ue432\ue433\ue434\ue435\ue436\ue437\ue438\ue439\ue43a\ue43b\ue43c\ue43d\ue43e\ue43f\ue440\ue441\ue442\ue443\ue444\ue445\ue446\ue447\ue448\ue449\ue44a\ue44b\ue44c\ue44d\ue44e\ue44f\ue450\ue451\ue452\ue453\ue454\ue455\ue456\ue457\ue458\ue459\ue45a\ue45b\ue45c\ue45d\ue45e\ue45f\ue460\ue461\ue462\ue463\ue464\ue465\ue466\ue467\ue468\ue469\ue46a\ue46b\ue46c\ue46d\ue46e\ue46f\ue470\ue471\ue472\ue473\ue474\ue475\ue476\ue477\ue478\ue479\ue47a\ue47b\ue47c\ue47d\ue47e\ue47f\ue480\ue481\ue482\ue483\ue484\ue485\ue486\ue487\ue488\ue489
 \ue48a\ue48b\ue48c\ue48d\ue48e\ue48f\ue490\ue491\ue492\ue493\ue494\ue495\ue496\ue497\ue498\ue499\ue49a\ue49b\ue49c\ue49d\ue49e\ue49f\ue4a0\ue4a1\ue4a2\ue4a3\ue4a4\ue4a5\ue4a6\ue4a7\ue4a8\ue4a9\ue4aa\ue4ab\ue4ac\ue4ad\ue4ae\ue4af\ue4b0\ue4b1\ue4b2\ue4b3\ue4b4\ue4b5\ue4b6\ue4b7\ue4b8\ue4b9\ue4ba\ue4bb\ue4bc\ue4bd\ue4be\ue4bf\ue4c0\ue4c1\ue4c2\ue4c3\ue4c4\ue4c5\ue4c6\ue4c7\ue4c8\ue4c9\ue4ca\ue4cb\ue4cc\ue4cd\ue4ce\ue4cf\ue4d0\ue4d1\ue4d2\ue4d3\ue4d4\ue4d5\ue4d6\ue4d7\ue4d8\ue4d9\ue4da\ue4db\ue4dc\ue4dd\ue4de\ue4df\ue4e0\ue4e1\ue4e2\ue4e3\ue4e4\ue4e5\ue4e6\ue4e7\ue4e8\ue4e9\ue4ea\ue4eb\ue4ec\ue4ed\ue4ee\ue4ef\ue4f0\ue4f1\ue4f2\ue4f3\ue4f4\ue4f5\ue4f6\ue4f7\ue4f8\ue4f9\ue4fa\ue4fb\ue4fc\ue4fd\ue4fe\ue4ff\ue500\ue501\ue502\ue503\ue504\ue505\ue506\ue507\ue508\ue509\ue50a\ue50b\ue50c\ue50d\ue50e\ue50f\ue510\ue511\ue512\ue513\ue514\ue515\ue516\ue517\ue518\ue519\ue51a\ue51b\ue51c\ue51d\ue51e\ue51f\ue520\ue521\ue522\ue523\ue524\ue525\ue526\ue527\ue528\ue529\ue52a\ue52b\ue52c\ue52d\ue52e\ue52f\
 ue530\ue531\ue532\ue533\ue534\ue535\ue536\ue537\ue538\ue539\ue53a\ue53b\ue53c\ue53d\ue53e\ue53f\ue540\ue541\ue542\ue543\ue544\ue545\ue546\ue547\ue548\ue549\ue54a\ue54b\ue54c\ue54d\ue54e\ue54f\ue550\ue551\ue552\ue553\ue554\ue555\ue556\ue557\ue558\ue559\ue55a\ue55b\ue55c\ue55d\ue55e\ue55f\ue560\ue561\ue562\ue563\ue564\ue565\ue566\ue567\ue568\ue569\ue56a\ue56b\ue56c\ue56d\ue56e\ue56f\ue570\ue571\ue572\ue573\ue574\ue575\ue576\ue577\ue578\ue579\ue57a\ue57b\ue57c\ue57d\ue57e\ue57f\ue580\ue581\ue582\ue583\ue584\ue585\ue586\ue587\ue588\ue589\ue58a\ue58b\ue58c\ue58d\ue58e\ue58f\ue590\ue591\ue592\ue593\ue594\ue595\ue596\ue597\ue598\ue599\ue59a\ue59b\ue59c\ue59d\ue59e\ue59f\ue5a0\ue5a1\ue5a2\ue5a3\ue5a4\ue5a5\ue5a6\ue5a7\ue5a8\ue5a9\ue5aa\ue5ab\ue5ac\ue5ad\ue5ae\ue5af\ue5b0\ue5b1\ue5b2\ue5b3\ue5b4\ue5b5\ue5b6\ue5b7\ue5b8\ue5b9\ue5ba\ue5bb\ue5bc\ue5bd\ue5be\ue5bf\ue5c0\ue5c1\ue5c2\ue5c3\ue5c4\ue5c5\ue5c6\ue5c7\ue5c8\ue5c9\ue5ca\ue5cb\ue5cc\ue5cd\ue5ce\ue5cf\ue5d0\ue5d1\ue5d2\ue5d3\ue5d4\ue5d5\u
 e5d6\ue5d7\ue5d8\ue5d9\ue5da\ue5db\ue5dc\ue5dd\ue5de\ue5df\ue5e0\ue5e1\ue5e2\ue5e3\ue5e4\ue5e5\ue5e6\ue5e7\ue5e8\ue5e9\ue5ea\ue5eb\ue5ec\ue5ed\ue5ee\ue5ef\ue5f0\ue5f1\ue5f2\ue5f3\ue5f4\ue5f5\ue5f6\ue5f7\ue5f8\ue5f9\ue5fa\ue5fb\ue5fc\ue5fd\ue5fe\ue5ff\ue600\ue601\ue602\ue603\ue604\ue605\ue606\ue607\ue608\ue609\ue60a\ue60b\ue60c\ue60d\ue60e\ue60f\ue610\ue611\ue612\ue613\ue614\ue615\ue616\ue617\ue618\ue619\ue61a\ue61b\ue61c\ue61d\ue61e\ue61f\ue620\ue621\ue622\ue623\ue624\ue625\ue626\ue627\ue628\ue629\ue62a\ue62b\ue62c\ue62d\ue62e\ue62f\ue630\ue631\ue632\ue633\ue634\ue635\ue636\ue637\ue638\ue639\ue63a\ue63b\ue63c\ue63d\ue63e\ue63f\ue640\ue641\ue642\ue643\ue644\ue645\ue646\ue647\ue648\ue649\ue64a\ue64b\ue64c\ue64d\ue64e\ue64f\ue650\ue651\ue652\ue653\ue654\ue655\ue656\ue657\ue658\ue659\ue65a\ue65b\ue65c\ue65d\ue65e\ue65f\ue660\ue661\ue662\ue663\ue664\ue665\ue666\ue667\ue668\ue669\ue66a\ue66b\ue66c\ue66d\ue66e\ue66f\ue670\ue671\ue672\ue673\ue674\ue675\ue676\ue677\ue678\ue679\ue67a\ue67b\ue
 67c\ue67d\ue67e\ue67f\ue680\ue681\ue682\ue683\ue684\ue685\ue686\ue687\ue688\ue689\ue68a\ue68b\ue68c\ue68d\ue68e\ue68f\ue690\ue691\ue692\ue693\ue694\ue695\ue696\ue697\ue698\ue699\ue69a\ue69b\ue69c\ue69d\ue69e\ue69f\ue6a0\ue6a1\ue6a2\ue6a3\ue6a4\ue6a5\ue6a6\ue6a7\ue6a8\ue6a9\ue6aa\ue6ab\ue6ac\ue6ad\ue6ae\ue6af\ue6b0\ue6b1\ue6b2\ue6b3\ue6b4\ue6b5\ue6b6\ue6b7\ue6b8\ue6b9\ue6ba\ue6bb\ue6bc\ue6bd\ue6be\ue6bf\ue6c0\ue6c1\ue6c2\ue6c3\ue6c4\ue6c5\ue6c6\ue6c7\ue6c8\ue6c9\ue6ca\ue6cb\ue6cc\ue6cd\ue6ce\ue6cf\ue6d0\ue6d1\ue6d2\ue6d3\ue6d4\ue6d5\ue6d6\ue6d7\ue6d8\ue6d9\ue6da\ue6db\ue6dc\ue6dd\ue6de\ue6df\ue6e0\ue6e1\ue6e2\ue6e3\ue6e4\ue6e5\ue6e6\ue6e7\ue6e8\ue6e9\ue6ea\ue6eb\ue6ec\ue6ed\ue6ee\ue6ef\ue6f0\ue6f1\ue6f2\ue6f3\ue6f4\ue6f5\ue6f6\ue6f7\ue6f8\ue6f9\ue6fa\ue6fb\ue6fc\ue6fd\ue6fe\ue6ff\ue700\ue701\ue702\ue703\ue704\ue705\ue706\ue707\ue708\ue709\ue70a\ue70b\ue70c\ue70d\ue70e\ue70f\ue710\ue711\ue712\ue713\ue714\ue715\ue716\ue717\ue718\ue719\ue71a\ue71b\ue71c\ue71d\ue71e\ue71f\ue720\ue721\ue7
 22\ue723\ue724\ue725\ue726\ue727\ue728\ue729\ue72a\ue72b\ue72c\ue72d\ue72e\ue72f\ue730\ue731\ue732\ue733\ue734\ue735\ue736\ue737\ue738\ue739\ue73a\ue73b\ue73c\ue73d\ue73e\ue73f\ue740\ue741\ue742\ue743\ue744\ue745\ue746\ue747\ue748\ue749\ue74a\ue74b\ue74c\ue74d\ue74e\ue74f\ue750\ue751\ue752\ue753\ue754\ue755\ue756\ue757\ue758\ue759\ue75a\ue75b\ue75c\ue75d\ue75e\ue75f\ue760\ue761\ue762\ue763\ue764\ue765\ue766\ue767\ue768\ue769\ue76a\ue76b\ue76c\ue76d\ue76e\ue76f\ue770\ue771\ue772\ue773\ue774\ue775\ue776\ue777\ue778\ue779\ue77a\ue77b\ue77c\ue77d\ue77e\ue77f\ue780\ue781\ue782\ue783\ue784\ue785\ue786\ue787\ue788\ue789\ue78a\ue78b\ue78c\ue78d\ue78e\ue78f\ue790\ue791\ue792\ue793\ue794\ue795\ue796\ue797\ue798\ue799\ue79a\ue79b\ue79c\ue79d\ue79e\ue79f\ue7a0\ue7a1\ue7a2\ue7a3\ue7a4\ue7a5\ue7a6\ue7a7\ue7a8\ue7a9\ue7aa\ue7ab\ue7ac\ue7ad\ue7ae\ue7af\ue7b0\ue7b1\ue7b2\ue7b3\ue7b4\ue7b5\ue7b6\ue7b7\ue7b8\ue7b9\ue7ba\ue7bb\ue7bc\ue7bd\ue7be\ue7bf\ue7c0\ue7c1\ue7c2\ue7c3\ue7c4\ue7c5\ue7c6\ue7c7\ue7c
 8\ue7c9\ue7ca\ue7cb\ue7cc\ue7cd\ue7ce\ue7cf\ue7d0\ue7d1\ue7d2\ue7d3\ue7d4\ue7d5\ue7d6\ue7d7\ue7d8\ue7d9\ue7da\ue7db\ue7dc\ue7dd\ue7de\ue7df\ue7e0\ue7e1\ue7e2\ue7e3\ue7e4\ue7e5\ue7e6\ue7e7\ue7e8\ue7e9\ue7ea\ue7eb\ue7ec\ue7ed\ue7ee\ue7ef\ue7f0\ue7f1\ue7f2\ue7f3\ue7f4\ue7f5\ue7f6\ue7f7\ue7f8\ue7f9\ue7fa\ue7fb\ue7fc\ue7fd\ue7fe\ue7ff\ue800\ue801\ue802\ue803\ue804\ue805\ue806\ue807\ue808\ue809\ue80a\ue80b\ue80c\ue80d\ue80e\ue80f\ue810\ue811\ue812\ue813\ue814\ue815\ue816\ue817\ue818\ue819\ue81a\ue81b\ue81c\ue81d\ue81e\ue81f\ue820\ue821\ue822\ue823\ue824\ue825\ue826\ue827\ue828\ue829\ue82a\ue82b\ue82c\ue82d\ue82e\ue82f\ue830\ue831\ue832\ue833\ue834\ue835\ue836\ue837\ue838\ue839\ue83a\ue83b\ue83c\ue83d\ue83e\ue83f\ue840\ue841\ue842\ue843\ue844\ue845\ue846\ue847\ue848\ue849\ue84a\ue84b\ue84c\ue84d\ue84e\ue84f\ue850\ue851\ue852\ue853\ue854\ue855\ue856\ue857\ue858\ue859\ue85a\ue85b\ue85c\ue85d\ue85e\ue85f\ue860\ue861\ue862\ue863\ue864\ue865\ue866\ue867\ue868\ue869\ue86a\ue86b\ue86c\ue86d\ue86e
 \ue86f\ue870\ue871\ue872\ue873\ue874\ue875\ue876\ue877\ue878\ue879\ue87a\ue87b\ue87c\ue87d\ue87e\ue87f\ue880\ue881\ue882\ue883\ue884\ue885\ue886\ue887\ue888\ue889\ue88a\ue88b\ue88c\ue88d\ue88e\ue88f\ue890\ue891\ue892\ue893\ue894\ue895\ue896\ue897\ue898\ue899\ue89a\ue89b\ue89c\ue89d\ue89e\ue89f\ue8a0\ue8a1\ue8a2\ue8a3\ue8a4\ue8a5\ue8a6\ue8a7\ue8a8\ue8a9\ue8aa\ue8ab\ue8ac\ue8ad\ue8ae\ue8af\ue8b0\ue8b1\ue8b2\ue8b3\ue8b4\ue8b5\ue8b6\ue8b7\ue8b8\ue8b9\ue8ba\ue8bb\ue8bc\ue8bd\ue8be\ue8bf\ue8c0\ue8c1\ue8c2\ue8c3\ue8c4\ue8c5\ue8c6\ue8c7\ue8c8\ue8c9\ue8ca\ue8cb\ue8cc\ue8cd\ue8ce\ue8cf\ue8d0\ue8d1\ue8d2\ue8d3\ue8d4\ue8d5\ue8d6\ue8d7\ue8d8\ue8d9\ue8da\ue8db\ue8dc\ue8dd\ue8de\ue8df\ue8e0\ue8e1\ue8e2\ue8e3\ue8e4\ue8e5\ue8e6\ue8e7\ue8e8\ue8e9\ue8ea\ue8eb\ue8ec\ue8ed\ue8ee\ue8ef\ue8f0\ue8f1\ue8f2\ue8f3\ue8f4\ue8f5\ue8f6\ue8f7\ue8f8\ue8f9\ue8fa\ue8fb\ue8fc\ue8fd\ue8fe\ue8ff\ue900\ue901\ue902\ue903\ue904\ue905\ue906\ue907\ue908\ue909\ue90a\ue90b\ue90c\ue90d\ue90e\ue90f\ue910\ue911\ue912\ue913\ue914\
 ue915\ue916\ue917\ue918\ue919\ue91a\ue91b\ue91c\ue91d\ue91e\ue91f\ue920\ue921\ue922\ue923\ue924\ue925\ue926\ue927\ue928\ue929\ue92a\ue92b\ue92c\ue92d\ue92e\ue92f\ue930\ue931\ue932\ue933\ue934\ue935\ue936\ue937\ue938\ue939\ue93a\ue93b\ue93c\ue93d\ue93e\ue93f\ue940\ue941\ue942\ue943\ue944\ue945\ue946\ue947\ue948\ue949\ue94a\ue94b\ue94c\ue94d\ue94e\ue94f\ue950\ue951\ue952\ue953\ue954\ue955\ue956\ue957\ue958\ue959\ue95a\ue95b\ue95c\ue95d\ue95e\ue95f\ue960\ue961\ue962\ue963\ue964\ue965\ue966\ue967\ue968\ue969\ue96a\ue96b\ue96c\ue96d\ue96e\ue96f\ue970\ue971\ue972\ue973\ue974\ue975\ue976\ue977\ue978\ue979\ue97a\ue97b\ue97c\ue97d\ue97e\ue97f\ue980\ue981\ue982\ue983\ue984\ue985\ue986\ue987\ue988\ue989\ue98a\ue98b\ue98c\ue98d\ue98e\ue98f\ue990\ue991\ue992\ue993\ue994\ue995\ue996\ue997\ue998\ue999\ue99a\ue99b\ue99c\ue99d\ue99e\ue99f\ue9a0\ue9a1\ue9a2\ue9a3\ue9a4\ue9a5\ue9a6\ue9a7\ue9a8\ue9a9\ue9aa\ue9ab\ue9ac\ue9ad\ue9ae\ue9af\ue9b0\ue9b1\ue9b2\ue9b3\ue9b4\ue9b5\ue9b6\ue9b7\ue9b8\ue9b9\ue9ba\u
 e9bb\ue9bc\ue9bd\ue9be\ue9bf\ue9c0\ue9c1\ue9c2\ue9c3\ue9c4\ue9c5\ue9c6\ue9c7\ue9c8\ue9c9\ue9ca\ue9cb\ue9cc\ue9cd\ue9ce\ue9cf\ue9d0\ue9d1\ue9d2\ue9d3\ue9d4\ue9d5\ue9d6\ue9d7\ue9d8\ue9d9\ue9da\ue9db\ue9dc\ue9dd\ue9de\ue9df\ue9e0\ue9e1\ue9e2\ue9e3\ue9e4\ue9e5\ue9e6\ue9e7\ue9e8\ue9e9\ue9ea\ue9eb\ue9ec\ue9ed\ue9ee\ue9ef\ue9f0\ue9f1\ue9f2\ue9f3\ue9f4\ue9f5\ue9f6\ue9f7\ue9f8\ue9f9\ue9fa\ue9fb\ue9fc\ue9fd\ue9fe\ue9ff\uea00\uea01\uea02\uea03\uea04\uea05\uea06\uea07\uea08\uea09\uea0a\uea0b\uea0c\uea0d\uea0e\uea0f\uea10\uea11\uea12\uea13\uea14\uea15\uea16\uea17\uea18\uea19\uea1a\uea1b\uea1c\uea1d\uea1e\uea1f\uea20\uea21\uea22\uea23\uea24\uea25\uea26\uea27\uea28\uea29\uea2a\uea2b\uea2c\uea2d\uea2e\uea2f\uea30\uea31\uea32\uea33\uea34\uea35\uea36\uea37\uea38\uea39\uea3a\uea3b\uea3c\uea3d\uea3e\uea3f\uea40\uea41\uea42\uea43\uea44\uea45\uea46\uea47\uea48\uea49\uea4a\uea4b\uea4c\uea4d\uea4e\uea4f\uea50\uea51\uea52\uea53\uea54\uea55\uea56\uea57\uea58\uea59\uea5a\uea5b\uea5c\uea5d\uea5e\uea5f\uea60\ue
 a61\uea62\uea63\uea64\uea65\uea66\uea67\uea68\uea69\uea6a\uea6b\uea6c\uea6d\uea6e\uea6f\uea70\uea71\uea72\uea73\uea74\uea75\uea76\uea77\uea78\uea79\uea7a\uea7b\uea7c\uea7d\uea7e\uea7f\uea80\uea81\uea82\uea83\uea84\uea85\uea86\uea87\uea88\uea89\uea8a\uea8b\uea8c\uea8d\uea8e\uea8f\uea90\uea91\uea92\uea93\uea94\uea95\uea96\uea97\uea98\uea99\uea9a\uea9b\uea9c\uea9d\uea9e\uea9f\ueaa0\ueaa1\ueaa2\ueaa3\ueaa4\ueaa5\ueaa6\ueaa7\ueaa8\ueaa9\ueaaa\ueaab\ueaac\ueaad\ueaae\ueaaf\ueab0\ueab1\ueab2\ueab3\ueab4\ueab5\ueab6\ueab7\ueab8\ueab9\ueaba\ueabb\ueabc\ueabd\ueabe\ueabf\ueac0\ueac1\ueac2\ueac3\ueac4\ueac5\ueac6\ueac7\ueac8\ueac9\ueaca\ueacb\ueacc\ueacd\ueace\ueacf\uead0\uead1\uead2\uead3\uead4\uead5\uead6\uead7\uead8\uead9\ueada\ueadb\ueadc\ueadd\ueade\ueadf\ueae0\ueae1\ueae2\ueae3\ueae4\ueae5\ueae6\ueae7\ueae8\ueae9\ueaea\ueaeb\ueaec\ueaed\ueaee\ueaef\ueaf0\ueaf1\ueaf2\ueaf3\ueaf4\ueaf5\ueaf6\ueaf7\ueaf8\ueaf9\ueafa\ueafb\ueafc\ueafd\ueafe\ueaff\ueb00\ueb01\ueb02\ueb03\ueb04\ueb05\ueb06\ueb
 07\ueb08\ueb09\ueb0a\ueb0b\ueb0c\ueb0d\ueb0e\ueb0f\ueb10\ueb11\ueb12\ueb13\ueb14\ueb15\ueb16\ueb17\ueb18\ueb19\ueb1a\ueb1b\ueb1c\ueb1d\ueb1e\ueb1f\ueb20\ueb21\ueb22\ueb23\ueb24\ueb25\ueb26\ueb27\ueb28\ueb29\ueb2a\ueb2b\ueb2c\ueb2d\ueb2e\ueb2f\ueb30\ueb31\ueb32\ueb33\ueb34\ueb35\ueb36\ueb37\ueb38\ueb39\ueb3a\ueb3b\ueb3c\ueb3d\ueb3e\ueb3f\ueb40\ueb41\ueb42\ueb43\ueb44\ueb45\ueb46\ueb47\ueb48\ueb49\ueb4a\ueb4b\ueb4c\ueb4d\ueb4e\ueb4f\ueb50\ueb51\ueb52\ueb53\ueb54\ueb55\ueb56\ueb57\ueb58\ueb59\ueb5a\ueb5b\ueb5c\ueb5d\ueb5e\ueb5f\ueb60\ueb61\ueb62\ueb63\ueb64\ueb65\ueb66\ueb67\ueb68\ueb69\ueb6a\ueb6b\ueb6c\ueb6d\ueb6e\ueb6f\ueb70\ueb71\ueb72\ueb73\ueb74\ueb75\ueb76\ueb77\ueb78\ueb79\ueb7a\ueb7b\ueb7c\ueb7d\ueb7e\ueb7f\ueb80\ueb81\ueb82\ueb83\ueb84\ueb85\ueb86\ueb87\ueb88\ueb89\ueb8a\ueb8b\ueb8c\ueb8d\ueb8e\ueb8f\ueb90\ueb91\ueb92\ueb93\ueb94\ueb95\ueb96\ueb97\ueb98\ueb99\ueb9a\ueb9b\ueb9c\ueb9d\ueb9e\ueb9f\ueba0\ueba1\ueba2\ueba3\ueba4\ueba5\ueba6\ueba7\ueba8\ueba9\uebaa\uebab\uebac\ueba
 d\uebae\uebaf\uebb0\uebb1\uebb2\uebb3\uebb4\uebb5\uebb6\uebb7\uebb8\uebb9\uebba\uebbb\uebbc\uebbd\uebbe\uebbf\uebc0\uebc1\uebc2\uebc3\uebc4\uebc5\uebc6\uebc7\uebc8\uebc9\uebca\uebcb\uebcc\uebcd\uebce\uebcf\uebd0\uebd1\uebd2\uebd3\uebd4\uebd5\uebd6\uebd7\uebd8\uebd9\uebda\uebdb\uebdc\uebdd\uebde\uebdf\uebe0\uebe1\uebe2\uebe3\uebe4\uebe5\uebe6\uebe7\uebe8\uebe9\uebea\uebeb\uebec\uebed\uebee\uebef\uebf0\uebf1\uebf2\uebf3\uebf4\uebf5\uebf6\uebf7\uebf8\uebf9\uebfa\uebfb\uebfc\uebfd\uebfe\uebff\uec00\uec01\uec02\uec03\uec04\uec05\uec06\uec07\uec08\uec09\uec0a\uec0b\uec0c\uec0d\uec0e\uec0f\uec10\uec11\uec12\uec13\uec14\uec15\uec16\uec17\uec18\uec19\uec1a\uec1b\uec1c\uec1d\uec1e\uec1f\uec20\uec21\uec22\uec23\uec24\uec25\uec26\uec27\uec28\uec29\uec2a\uec2b\uec2c\uec2d\uec2e\uec2f\uec30\uec31\uec32\uec33\uec34\uec35\uec36\uec37\uec38\uec39\uec3a\uec3b\uec3c\uec3d\uec3e\uec3f\uec40\uec41\uec42\uec43\uec44\uec45\uec46\uec47\uec48\uec49\uec4a\uec4b\uec4c\uec4d\uec4e\uec4f\uec50\uec51\uec52\uec53
 \uec54\uec55\uec56\uec57\uec58\uec59\uec5a\uec5b\uec5c\uec5d\uec5e\uec5f\uec60\uec61\uec62\uec63\uec64\uec65\uec66\uec67\uec68\uec69\uec6a\uec6b\uec6c\uec6d\uec6e\uec6f\uec70\uec71\uec72\uec73\uec74\uec75\uec76\uec77\uec78\uec79\uec7a\uec7b\uec7c\uec7d\uec7e\uec7f\uec80\uec81\uec82\uec83\uec84\uec85\uec86\uec87\uec88\uec89\uec8a\uec8b\uec8c\uec8d\uec8e\uec8f\uec90\uec91\uec92\uec93\uec94\uec95\uec96\uec97\uec98\uec99\uec9a\uec9b\uec9c\uec9d\uec9e\uec9f\ueca0\ueca1\ueca2\ueca3\ueca4\ueca5\ueca6\ueca7\ueca8\ueca9\uecaa\uecab\uecac\uecad\uecae\uecaf\uecb0\uecb1\uecb2\uecb3\uecb4\uecb5\uecb6\uecb7\uecb8\uecb9\uecba\uecbb\uecbc\uecbd\uecbe\uecbf\uecc0\uecc1\uecc2\uecc3\uecc4\uecc5\uecc6\uecc7\uecc8\uecc9\uecca\ueccb\ueccc\ueccd\uecce\ueccf\uecd0\uecd1\uecd2\uecd3\uecd4\uecd5\uecd6\uecd7\uecd8\uecd9\uecda\uecdb\uecdc\uecdd\uecde\uecdf\uece0\uece1\uece2\uece3\uece4\uece5\uece6\uece7\uece8\uece9\uecea\ueceb\uecec\ueced\uecee\uecef\uecf0\uecf1\uecf2\uecf3\uecf4\uecf5\uecf6\uecf7\uecf8\uecf9\
 uecfa\uecfb\uecfc\uecfd\uecfe\uecff\ued00\ued01\ued02\ued03\ued04\ued05\ued06\ued07\ued08\ued09\ued0a\ued0b\ued0c\ued0d\ued0e\ued0f\ued10\ued11\ued12\ued13\ued14\ued15\ued16\ued17\ued18\ued19\ued1a\ued1b\ued1c\ued1d\ued1e\ued1f\ued20\ued21\ued22\ued23\ued24\ued25\ued26\ued27\ued28\ued29\ued2a\ued2b\ued2c\ued2d\ued2e\ued2f\ued30\ued31\ued32\ued33\ued34\ued35\ued36\ued37\ued38\ued39\ued3a\ued3b\ued3c\ued3d\ued3e\ued3f\ued40\ued41\ued42\ued43\ued44\ued45\ued46\ued47\ued48\ued49\ued4a\ued4b\ued4c\ued4d\ued4e\ued4f\ued50\ued51\ued52\ued53\ued54\ued55\ued56\ued57\ued58\ued59\ued5a\ued5b\ued5c\ued5d\ued5e\ued5f\ued60\ued61\ued62\ued63\ued64\ued65\ued66\ued67\ued68\ued69\ued6a\ued6b\ued6c\ued6d\ued6e\ued6f\ued70\ued71\ued72\ued73\ued74\ued75\ued76\ued77\ued78\ued79\ued7a\ued7b\ued7c\ued7d\ued7e\ued7f\ued80\ued81\ued82\ued83\ued84\ued85\ued86\ued87\ued88\ued89\ued8a\ued8b\ued8c\ued8d\ued8e\ued8f\ued90\ued91\ued92\ued93\ued94\ued95\ued96\ued97\ued98\ued99\ued9a\ued9b\ued9c\ued9d\ued9e\ued9f\u
 eda0\ueda1\ueda2\ueda3\ueda4\ueda5\ueda6\ueda7\ueda8\ueda9\uedaa\uedab\uedac\uedad\uedae\uedaf\uedb0\uedb1\uedb2\uedb3\uedb4\uedb5\uedb6\uedb7\uedb8\uedb9\uedba\uedbb\uedbc\uedbd\uedbe\uedbf\uedc0\uedc1\uedc2\uedc3\uedc4\uedc5\uedc6\uedc7\uedc8\uedc9\uedca\uedcb\uedcc\uedcd\uedce\uedcf\uedd0\uedd1\uedd2\uedd3\uedd4\uedd5\uedd6\uedd7\uedd8\uedd9\uedda\ueddb\ueddc\ueddd\uedde\ueddf\uede0\uede1\uede2\uede3\uede4\uede5\uede6\uede7\uede8\uede9\uedea\uedeb\uedec\ueded\uedee\uedef\uedf0\uedf1\uedf2\uedf3\uedf4\uedf5\uedf6\uedf7\uedf8\uedf9\uedfa\uedfb\uedfc\uedfd\uedfe\uedff\uee00\uee01\uee02\uee03\uee04\uee05\uee06\uee07\uee08\uee09\uee0a\uee0b\uee0c\uee0d\uee0e\uee0f\uee10\uee11\uee12\uee13\uee14\uee15\uee16\uee17\uee18\uee19\uee1a\uee1b\uee1c\uee1d\uee1e\uee1f\uee20\uee21\uee22\uee23\uee24\uee25\uee26\uee27\uee28\uee29\uee2a\uee2b\uee2c\uee2d\uee2e\uee2f\uee30\uee31\uee32\uee33\uee34\uee35\uee36\uee37\uee38\uee39\uee3a\uee3b\uee3c\uee3d\uee3e\uee3f\uee40\uee41\uee42\uee43\uee44\uee45\ue
 e46\uee47\uee48\uee49\uee4a\uee4b\uee4c\uee4d\uee4e\uee4f\uee50\uee51\uee52\uee53\uee54\uee55\uee56\uee57\uee58\uee59\uee5a\uee5b\uee5c\uee5d\uee5e\uee5f\uee60\uee61\uee62\uee63\uee64\uee65\uee66\uee67\uee68\uee69\uee6a\uee6b\uee6c\uee6d\uee6e\uee6f\uee70\uee71\uee72\uee73\uee74\uee75\uee76\uee77\uee78\uee79\uee7a\uee7b\uee7c\uee7d\uee7e\uee7f\uee80\uee81\uee82\uee83\uee84\uee85\uee86\uee87\uee88\uee89\uee8a\uee8b\uee8c\uee8d\uee8e\uee8f\uee90\uee91\uee92\uee93\uee94\uee95\uee96\uee97\uee98\uee99\uee9a\uee9b\uee9c\uee9d\uee9e\uee9f\ueea0\ueea1\ueea2\ueea3\ueea4\ueea5\ueea6\ueea7\ueea8\ueea9\ueeaa\ueeab\ueeac\ueead\ueeae\ueeaf\ueeb0\ueeb1\ueeb2\ueeb3\ueeb4\ueeb5\ueeb6\ueeb7\ueeb8\ueeb9\ueeba\ueebb\ueebc\ueebd\ueebe\ueebf\ueec0\ueec1\ueec2\ueec3\ueec4\ueec5\ueec6\ueec7\ueec8\ueec9\ueeca\ueecb\ueecc\ueecd\ueece\ueecf\ueed0\ueed1\ueed2\ueed3\ueed4\ueed5\ueed6\ueed7\ueed8\ueed9\ueeda\ueedb\ueedc\ueedd\ueede\ueedf\ueee0\ueee1\ueee2\ueee3\ueee4\ueee5\ueee6\ueee7\ueee8\ueee9\ueeea\ueeeb\uee
 ec\ueeed\ueeee\ueeef\ueef0\ueef1\ueef2\ueef3\ueef4\ueef5\ueef6\ueef7\ueef8\ueef9\ueefa\ueefb\ueefc\ueefd\ueefe\ueeff\uef00\uef01\uef02\uef03\uef04\uef05\uef06\uef07\uef08\uef09\uef0a\uef0b\uef0c\uef0d\uef0e\uef0f\uef10\uef11\uef12\uef13\uef14\uef15\uef16\uef17\uef18\uef19\uef1a\uef1b\uef1c\uef1d\uef1e\uef1f\uef20\uef21\uef22\uef23\uef24\uef25\uef26\uef27\uef28\uef29\uef2a\uef2b\uef2c\uef2d\uef2e\uef2f\uef30\uef31\uef32\uef33\uef34\uef35\uef36\uef37\uef38\uef39\uef3a\uef3b\uef3c\uef3d\uef3e\uef3f\uef40\uef41\uef42\uef43\uef44\uef45\uef46\uef47\uef48\uef49\uef4a\uef4b\uef4c\uef4d\uef4e\uef4f\uef50\uef51\uef52\uef53\uef54\uef55\uef56\uef57\uef58\uef59\uef5a\uef5b\uef5c\uef5d\uef5e\uef5f\uef60\uef61\uef62\uef63\uef64\uef65\uef66\uef67\uef68\uef69\uef6a\uef6b\uef6c\uef6d\uef6e\uef6f\uef70\uef71\uef72\uef73\uef74\uef75\uef76\uef77\uef78\uef79\uef7a\uef7b\uef7c\uef7d\uef7e\uef7f\uef80\uef81\uef82\uef83\uef84\uef85\uef86\uef87\uef88\uef89\uef8a\uef8b\uef8c\uef8d\uef8e\uef8f\uef90\uef91\uef9
 2\uef93\uef94\uef95\uef96\uef97\uef98\uef99\uef9a\uef9b\uef9c\uef9d\uef9e\uef9f\uefa0\uefa1\uefa2\uefa3\uefa4\uefa5\uefa6\uefa7\uefa8\uefa9\uefaa\uefab\uefac\uefad\uefae\uefaf\uefb0\uefb1\uefb2\uefb3\uefb4\uefb5\uefb6\uefb7\uefb8\uefb9\uefba\uefbb\uefbc\uefbd\uefbe\uefbf\uefc0\uefc1\uefc2\uefc3\uefc4\uefc5\uefc6\uefc7\uefc8\uefc9\uefca\uefcb\uefcc\uefcd\uefce\uefcf\uefd0\uefd1\uefd2\uefd3\uefd4\uefd5\uefd6\uefd7\uefd8\uefd9\uefda\uefdb\uefdc\uefdd\uefde\uefdf\uefe0\uefe1\uefe2\uefe3\uefe4\uefe5\uefe6\uefe7\uefe8\uefe9\uefea\uefeb\uefec\uefed\uefee\uefef\ueff0\ueff1\ueff2\ueff3\ueff4\ueff5\ueff6\ueff7\ueff8\ueff9\ueffa\ueffb\ueffc\ueffd\ueffe\uefff\uf000\uf001\uf002\uf003\uf004\uf005\uf006\uf007\uf008\uf009\uf00a\uf00b\uf00c\uf00d\uf00e\uf00f\uf010\uf011\uf012\uf013\uf014\uf015\uf016\uf017\uf018\uf019\uf01a\uf01b\uf01c\uf01d\uf01e\uf01f\uf020\uf021\uf022\uf023\uf024\uf025\uf026\uf027\uf028\uf029\uf02a\uf02b\uf02c\uf02d\uf02e\uf02f\uf030\uf031\uf032\uf033\uf034\uf035\uf036\uf037\uf038
 \uf039\uf03a\uf03b\uf03c\uf03d\uf03e\uf03f\uf040\uf041\uf042\uf043\uf044\uf045\uf046\uf047\uf048\uf049\uf04a\uf04b\uf04c\uf04d\uf04e\uf04f\uf050\uf051\uf052\uf053\uf054\uf055\uf056\uf057\uf058\uf059\uf05a\uf05b\uf05c\uf05d\uf05e\uf05f\uf060\uf061\uf062\uf063\uf064\uf065\uf066\uf067\uf068\uf069\uf06a\uf06b\uf06c\uf06d\uf06e\uf06f\uf070\uf071\uf072\uf073\uf074\uf075\uf076\uf077\uf078\uf079\uf07a\uf07b\uf07c\uf07d\uf07e\uf07f\uf080\uf081\uf082\uf083\uf084\uf085\uf086\uf087\uf088\uf089\uf08a\uf08b\uf08c\uf08d\uf08e\uf08f\uf090\uf091\uf092\uf093\uf094\uf095\uf096\uf097\uf098\uf099\uf09a\uf09b\uf09c\uf09d\uf09e\uf09f\uf0a0\uf0a1\uf0a2\uf0a3\uf0a4\uf0a5\uf0a6\uf0a7\uf0a8\uf0a9\uf0aa\uf0ab\uf0ac\uf0ad\uf0ae\uf0af\uf0b0\uf0b1\uf0b2\uf0b3\uf0b4\uf0b5\uf0b6\uf0b7\uf0b8\uf0b9\uf0ba\uf0bb\uf0bc\uf0bd\uf0be\uf0bf\uf0c0\uf0c1\uf0c2\uf0c3\uf0c4\uf0c5\uf0c6\uf0c7\uf0c8\uf0c9\uf0ca\uf0cb\uf0cc\uf0cd\uf0ce\uf0cf\uf0d0\uf0d1\uf0d2\uf0d3\uf0d4\uf0d5\uf0d6\uf0d7\uf0d8\uf0d9\uf0da\uf0db\uf0dc\uf0dd\uf0de\
 uf0df\uf0e0\uf0e1\uf0e2\uf0e3\uf0e4\uf0e5\uf0e6\uf0e7\uf0e8\uf0e9\uf0ea\uf0eb\uf0ec\uf0ed\uf0ee\uf0ef\uf0f0\uf0f1\uf0f2\uf0f3\uf0f4\uf0f5\uf0f6\uf0f7\uf0f8\uf0f9\uf0fa\uf0fb\uf0fc\uf0fd\uf0fe\uf0ff\uf100\uf101\uf102\uf103\uf104\uf105\uf106\uf107\uf108\uf109\uf10a\uf10b\uf10c\uf10d\uf10e\uf10f\uf110\uf111\uf112\uf113\uf114\uf115\uf116\uf117\uf118\uf119\uf11a\uf11b\uf11c\uf11d\uf11e\uf11f\uf120\uf121\uf122\uf123\uf124\uf125\uf126\uf127\uf128\uf129\uf12a\uf12b\uf12c\uf12d\uf12e\uf12f\uf130\uf131\uf132\uf133\uf134\uf135\uf136\uf137\uf138\uf139\uf13a\uf13b\uf13c\uf13d\uf13e\uf13f\uf140\uf141\uf142\uf143\uf144\uf145\uf146\uf147\uf148\uf149\uf14a\uf14b\uf14c\uf14d\uf14e\uf14f\uf150\uf151\uf152\uf153\uf154\uf155\uf156\uf157\uf158\uf159\uf15a\uf15b\uf15c\uf15d\uf15e\uf15f\uf160\uf161\uf162\uf163\uf164\uf165\uf166\uf167\uf168\uf169\uf16a\uf16b\uf16c\uf16d\uf16e\uf16f\uf170\uf171\uf172\uf173\uf174\uf175\uf176\uf177\uf178\uf179\uf17a\uf17b\uf17c\uf17d\uf17e\uf17f\uf180\uf181\uf182\uf183\uf184\u
 f185\uf186\uf187\uf188\uf189\uf18a\uf18b\uf18c\uf18d\uf18e\uf18f\uf190\uf191\uf192\uf193\uf194\uf195\uf196\uf197\uf198\uf199\uf19a\uf19b\uf19c\uf19d\uf19e\uf19f\uf1a0\uf1a1\uf1a2\uf1a3\uf1a4\uf1a5\uf1a6\uf1a7\uf1a8\uf1a9\uf1aa\uf1ab\uf1ac\uf1ad\uf1ae\uf1af\uf1b0\uf1b1\uf1b2\uf1b3\uf1b4\uf1b5\uf1b6\uf1b7\uf1b8\uf1b9\uf1ba\uf1bb\uf1bc\uf1bd\uf1be\uf1bf\uf1c0\uf1c1\uf1c2\uf1c3\uf1c4\uf1c5\uf1c6\uf1c7\uf1c8\uf1c9\uf1ca\uf1cb\uf1cc\uf1cd\uf1ce\uf1cf\uf1d0\uf1d1\uf1d2\uf1d3\uf1d4\uf1d5\uf1d6\uf1d7\uf1d8\uf1d9\uf1da\uf1db\uf1dc\uf1dd\uf1de\uf1df\uf1e0\uf1e1\uf1e2\uf1e3\uf1e4\uf1e5\uf1e6\uf1e7\uf1e8\uf1e9\uf1ea\uf1eb\uf1ec\uf1ed\uf1ee\uf1ef\uf1f0\uf1f1\uf1f2\uf1f3\uf1f4\uf1f5\uf1f6\uf1f7\uf1f8\uf1f9\uf1fa\uf1fb\uf1fc\uf1fd\uf1fe\uf1ff\uf200\uf201\uf202\uf203\uf204\uf205\uf206\uf207\uf208\uf209\uf20a\uf20b\uf20c\uf20d\uf20e\uf20f\uf210\uf211\uf212\uf213\uf214\uf215\uf216\uf217\uf218\uf219\uf21a\uf21b\uf21c\uf21d\uf21e\uf21f\uf220\uf221\uf222\uf223\uf224\uf225\uf226\uf227\uf228\uf229\uf22a\uf
 22b\uf22c\uf22d\uf22e\uf22f\uf230\uf231\uf232\uf233\uf234\uf235\uf236\uf237\uf238\uf239\uf23a\uf23b\uf23c\uf23d\uf23e\uf23f\uf240\uf241\uf242\uf243\uf244\uf245\uf246\uf247\uf248\uf249\uf24a\uf24b\uf24c\uf24d\uf24e\uf24f\uf250\uf251\uf252\uf253\uf254\uf255\uf256\uf257\uf258\uf259\uf25a\uf25b\uf25c\uf25d\uf25e\uf25f\uf260\uf261\uf262\uf263\uf264\uf265\uf266\uf267\uf268\uf269\uf26a\uf26b\uf26c\uf26d\uf26e\uf26f\uf270\uf271\uf272\uf273\uf274\uf275\uf276\uf277\uf278\uf279\uf27a\uf27b\uf27c\uf27d\uf27e\uf27f\uf280\uf281\uf282\uf283\uf284\uf285\uf286\uf287\uf288\uf289\uf28a\uf28b\uf28c\uf28d\uf28e\uf28f\uf290\uf291\uf292\uf293\uf294\uf295\uf296\uf297\uf298\uf299\uf29a\uf29b\uf29c\uf29d\uf29e\uf29f\uf2a0\uf2a1\uf2a2\uf2a3\uf2a4\uf2a5\uf2a6\uf2a7\uf2a8\uf2a9\uf2aa\uf2ab\uf2ac\uf2ad\uf2ae\uf2af\uf2b0\uf2b1\uf2b2\uf2b3\uf2b4\uf2b5\uf2b6\uf2b7\uf2b8\uf2b9\uf2ba\uf2bb\uf2bc\uf2bd\uf2be\uf2bf\uf2c0\uf2c1\uf2c2\uf2c3\uf2c4\uf2c5\uf2c6\uf2c7\uf2c8\uf2c9\uf2ca\uf2cb\uf2cc\uf2cd\uf2ce\uf2cf\uf2d0\uf2
 d1\uf2d2\uf2d3\uf2d4\uf2d5\uf2d6\uf2d7\uf2d8\uf2d9\uf2da\uf2db\uf2dc\uf2dd\uf2de\uf2df\uf2e0\uf2e1\uf2e2\uf2e3\uf2e4\uf2e5\uf2e6\uf2e7\uf2e8\uf2e9\uf2ea\uf2eb\uf2ec\uf2ed\uf2ee\uf2ef\uf2f0\uf2f1\uf2f2\uf2f3\uf2f4\uf2f5\uf2f6\uf2f7\uf2f8\uf2f9\uf2fa\uf2fb\uf2fc\uf2fd\uf2fe\uf2ff\uf300\uf301\uf302\uf303\uf304\uf305\uf306\uf307\uf308\uf309\uf30a\uf30b\uf30c\uf30d\uf30e\uf30f\uf310\uf311\uf312\uf313\uf314\uf315\uf316\uf317\uf318\uf319\uf31a\uf31b\uf31c\uf31d\uf31e\uf31f\uf320\uf321\uf322\uf323\uf324\uf325\uf326\uf327\uf328\uf329\uf32a\uf32b\uf32c\uf32d\uf32e\uf32f\uf330\uf331\uf332\uf333\uf334\uf335\uf336\uf337\uf338\uf339\uf33a\uf33b\uf33c\uf33d\uf33e\uf33f\uf340\uf341\uf342\uf343\uf344\uf345\uf346\uf347\uf348\uf349\uf34a\uf34b\uf34c\uf34d\uf34e\uf34f\uf350\uf351\uf352\uf353\uf354\uf355\uf356\uf357\uf358\uf359\uf35a\uf35b\uf35c\uf35d\uf35e\uf35f\uf360\uf361\uf362\uf363\uf364\uf365\uf366\uf367\uf368\uf369\uf36a\uf36b\uf36c\uf36d\uf36e\uf36f\uf370\uf371\uf372\uf373\uf374\uf375\uf376\uf37
 7\uf378\uf379\uf37a\uf37b\uf37c\uf37d\uf37e\uf37f\uf380\uf381\uf382\uf383\uf384\uf385\uf386\uf387\uf388\uf389\uf38a\uf38b\uf38c\uf38d\uf38e\uf38f\uf390\uf391\uf392\uf393\uf394\uf395\uf396\uf397\uf398\uf399\uf39a\uf39b\uf39c\uf39d\uf39e\uf39f\uf3a0\uf3a1\uf3a2\uf3a3\uf3a4\uf3a5\uf3a6\uf3a7\uf3a8\uf3a9\uf3aa\uf3ab\uf3ac\uf3ad\uf3ae\uf3af\uf3b0\uf3b1\uf3b2\uf3b3\uf3b4\uf3b5\uf3b6\uf3b7\uf3b8\uf3b9\uf3ba\uf3bb\uf3bc\uf3bd\uf3be\uf3bf\uf3c0\uf3c1\uf3c2\uf3c3\uf3c4\uf3c5\uf3c6\uf3c7\uf3c8\uf3c9\uf3ca\uf3cb\uf3cc\uf3cd\uf3ce\uf3cf\uf3d0\uf3d1\uf3d2\uf3d3\uf3d4\uf3d5\uf3d6\uf3d7\uf3d8\uf3d9\uf3da\uf3db\uf3dc\uf3dd\uf3de\uf3df\uf3e0\uf3e1\uf3e2\uf3e3\uf3e4\uf3e5\uf3e6\uf3e7\uf3e8\uf3e9\uf3ea\uf3eb\uf3ec\uf3ed\uf3ee\uf3ef\uf3f0\uf3f1\uf3f2\uf3f3\uf3f4\uf3f5\uf3f6\uf3f7\uf3f8\uf3f9\uf3fa\uf3fb\uf3fc\uf3fd\uf3fe\uf3ff\uf400\uf401\uf402\uf403\uf404\uf405\uf406\uf407\uf408\uf409\uf40a\uf40b\uf40c\uf40d\uf40e\uf40f\uf410\uf411\uf412\uf413\uf414\uf415\uf416\uf417\uf418\uf419\uf41a\uf41b\uf41c\uf41d
 \uf41e\uf41f\uf420\uf421\uf422\uf423\uf424\uf425\uf426\uf427\uf428\uf429\uf42a\uf42b\uf42c\uf42d\uf42e\uf42f\uf430\uf431\uf432\uf433\uf434\uf435\uf436\uf437\uf438\uf439\uf43a\uf43b\uf43c\uf43d\uf43e\uf43f\uf440\uf441\uf442\uf443\uf444\uf445\uf446\uf447\uf448\uf449\uf44a\uf44b\uf44c\uf44d\uf44e\uf44f\uf450\uf451\uf452\uf453\uf454\uf455\uf456\uf457\uf458\uf459\uf45a\uf45b\uf45c\uf45d\uf45e\uf45f\uf460\uf461\uf462\uf463\uf464\uf465\uf466\uf467\uf468\uf469\uf46a\uf46b\uf46c\uf46d\uf46e\uf46f\uf470\uf471\uf472\uf473\uf474\uf475\uf476\uf477\uf478\uf479\uf47a\uf47b\uf47c\uf47d\uf47e\uf47f\uf480\uf481\uf482\uf483\uf484\uf485\uf486\uf487\uf488\uf489\uf48a\uf48b\uf48c\uf48d\uf48e\uf48f\uf490\uf491\uf492\uf493\uf494\uf495\uf496\uf497\uf498\uf499\uf49a\uf49b\uf49c\uf49d\uf49e\uf49f\uf4a0\uf4a1\uf4a2\uf4a3\uf4a4\uf4a5\uf4a6\uf4a7\uf4a8\uf4a9\uf4aa\uf4ab\uf4ac\uf4ad\uf4ae\uf4af\uf4b0\uf4b1\uf4b2\uf4b3\uf4b4\uf4b5\uf4b6\uf4b7\uf4b8\uf4b9\uf4ba\uf4bb\uf4bc\uf4bd\uf4be\uf4bf\uf4c0\uf4c1\uf4c2\uf4c3\
 uf4c4\uf4c5\uf4c6\uf4c7\uf4c8\uf4c9\uf4ca\uf4cb\uf4cc\uf4cd\uf4ce\uf4cf\uf4d0\uf4d1\uf4d2\uf4d3\uf4d4\uf4d5\uf4d6\uf4d7\uf4d8\uf4d9\uf4da\uf4db\uf4dc\uf4dd\uf4de\uf4df\uf4e0\uf4e1\uf4e2\uf4e3\uf4e4\uf4e5\uf4e6\uf4e7\uf4e8\uf4e9\uf4ea\uf4eb\uf4ec\uf4ed\uf4ee\uf4ef\uf4f0\uf4f1\uf4f2\uf4f3\uf4f4\uf4f5\uf4f6\uf4f7\uf4f8\uf4f9\uf4fa\uf4fb\uf4fc\uf4fd\uf4fe\uf4ff\uf500\uf501\uf502\uf503\uf504\uf505\uf506\uf507\uf508\uf509\uf50a\uf50b\uf50c\uf50d\uf50e\uf50f\uf510\uf511\uf512\uf513\uf514\uf515\uf516\uf517\uf518\uf519\uf51a\uf51b\uf51c\uf51d\uf51e\uf51f\uf520\uf521\uf522\uf523\uf524\uf525\uf526\uf527\uf528\uf529\uf52a\uf52b\uf52c\uf52d\uf52e\uf52f\uf530\uf531\uf532\uf533\uf534\uf535\uf536\uf537\uf538\uf539\uf53a\uf53b\uf53c\uf53d\uf53e\uf53f\uf540\uf541\uf542\uf543\uf544\uf545\uf546\uf547\uf548\uf549\uf54a\uf54b\uf54c\uf54d\uf54e\uf54f\uf550\uf551\uf552\uf553\uf554\uf555\uf556\uf557\uf558\uf559\uf55a\uf55b\uf55c\uf55d\uf55e\uf55f\uf560\uf561\uf562\uf563\uf564\uf565\uf566\uf567\uf568\uf569\u
 f56a\uf56b\uf56c\uf56d\uf56e\uf56f\uf570\uf571\uf572\uf573\uf574\uf575\uf576\uf577\uf578\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf582\uf583\uf584\uf585\uf586\uf587\uf588\uf589\uf58a\uf58b\uf58c\uf58d\uf58e\uf58f\uf590\uf591\uf592\uf593\uf594\uf595\uf596\uf597\uf598\uf599\uf59a\uf59b\uf59c\uf59d\uf59e\uf59f\uf5a0\uf5a1\uf5a2\uf5a3\uf5a4\uf5a5\uf5a6\uf5a7\uf5a8\uf5a9\uf5aa\uf5ab\uf5ac\uf5ad\uf5ae\uf5af\uf5b0\uf5b1\uf5b2\uf5b3\uf5b4\uf5b5\uf5b6\uf5b7\uf5b8\uf5b9\uf5ba\uf5bb\uf5bc\uf5bd\uf5be\uf5bf\uf5c0\uf5c1\uf5c2\uf5c3\uf5c4\uf5c5\uf5c6\uf5c7\uf5c8\uf5c9\uf5ca\uf5cb\uf5cc\uf5cd\uf5ce\uf5cf\uf5d0\uf5d1\uf5d2\uf5d3\uf5d4\uf5d5\uf5d6\uf5d7\uf5d8\uf5d9\uf5da\uf5db\uf5dc\uf5dd\uf5de\uf5df\uf5e0\uf5e1\uf5e2\uf5e3\uf5e4\uf5e5\uf5e6\uf5e7\uf5e8\uf5e9\uf5ea\uf5eb\uf5ec\uf5ed\uf5ee\uf5ef\uf5f0\uf5f1\uf5f2\uf5f3\uf5f4\uf5f5\uf5f6\uf5f7\uf5f8\uf5f9\uf5fa\uf5fb\uf5fc\uf5fd\uf5fe\uf5ff\uf600\uf601\uf602\uf603\uf604\uf605\uf606\uf607\uf608\uf609\uf60a\uf60b\uf60c\uf60d\uf60e\uf60f\uf
 610\uf611\uf612\uf613\uf614\uf615\uf616\uf617\uf618\uf619\uf61a\uf61b\uf61c\uf61d\uf61e\uf61f\uf620\uf621\uf622\uf623\uf624\uf625\uf626\uf627\uf628\uf629\uf62a\uf62b\uf62c\uf62d\uf62e\uf62f\uf630\uf631\uf632\uf633\uf634\uf635\uf636\uf637\uf638\uf639\uf63a\uf63b\uf63c\uf63d\uf63e\uf63f\uf640\uf641\uf642\uf643\uf644\uf645\uf646\uf647\uf648\uf649\uf64a\uf64b\uf64c\uf64d\uf64e\uf64f\uf650\uf651\uf652\uf653\uf654\uf655\uf656\uf657\uf658\uf659\uf65a\uf65b\uf65c\uf65d\uf65e\uf65f\uf660\uf661\uf662\uf663\uf664\uf665\uf666\uf667\uf668\uf669\uf66a\uf66b\uf66c\uf66d\uf66e\uf66f\uf670\uf671\uf672\uf673\uf674\uf675\uf676\uf677\uf678\uf679\uf67a\uf67b\uf67c\uf67d\uf67e\uf67f\uf680\uf681\uf682\uf683\uf684\uf685\uf686\uf687\uf688\uf689\uf68a\uf68b\uf68c\uf68d\uf68e\uf68f\uf690\uf691\uf692\uf693\uf694\uf695\uf696\uf697\uf698\uf699\uf69a\uf69b\uf69c\uf69d\uf69e\uf69f\uf6a0\uf6a1\uf6a2\uf6a3\uf6a4\uf6a5\uf6a6\uf6a7\uf6a8\uf6a9\uf6aa\uf6ab\uf6ac\uf6ad\uf6ae\uf6af\uf6b0\uf6b1\uf6b2\uf6b3\uf6b4\uf6b5\uf6
 b6\uf6b7\uf6b8\uf6b9\uf6ba\uf6bb\uf6bc\uf6bd\uf6be\uf6bf\uf6c0\uf6c1\uf6c2\uf6c3\uf6c4\uf6c5\uf6c6\uf6c7\uf6c8\uf6c9\uf6ca\uf6cb\uf6cc\uf6cd\uf6ce\uf6cf\uf6d0\uf6d1\uf6d2\uf6d3\uf6d4\uf6d5\uf6d6\uf6d7\uf6d8\uf6d9\uf6da\uf6db\uf6dc\uf6dd\uf6de\uf6df\uf6e0\uf6e1\uf6e2\uf6e3\uf6e4\uf6e5\uf6e6\uf6e7\uf6e8\uf6e9\uf6ea\uf6eb\uf6ec\uf6ed\uf6ee\uf6ef\uf6f0\uf6f1\uf6f2\uf6f3\uf6f4\uf6f5\uf6f6\uf6f7\uf6f8\uf6f9\uf6fa\uf6fb\uf6fc\uf6fd\uf6fe\uf6ff\uf700\uf701\uf702\uf703\uf704\uf705\uf706\uf707\uf708\uf709\uf70a\uf70b\uf70c\uf70d\uf70e\uf70f\uf710\uf711\uf712\uf713\uf714\uf715\uf716\uf717\uf718\uf719\uf71a\uf71b\uf71c\uf71d\uf71e\uf71f\uf720\uf721\uf722\uf723\uf724\uf725\uf726\uf727\uf728\uf729\uf72a\uf72b\uf72c\uf72d\uf72e\uf72f\uf730\uf731\uf732\uf733\uf734\uf735\uf736\uf737\uf738\uf739\uf73a\uf73b\uf73c\uf73d\uf73e\uf73f\uf740\uf741\uf742\uf743\uf744\uf745\uf746\uf747\uf748\uf749\uf74a\uf74b\uf74c\uf74d\uf74e\uf74f\uf750\uf751\uf752\uf753\uf754\uf755\uf756\uf757\uf758\uf759\uf75a\uf75b\uf75
 c\uf75d\uf75e\uf75f\uf760\uf761\uf762\uf763\uf764\uf765\uf766\uf767\uf768\uf769\uf76a\uf76b\uf76c\uf76d\uf76e\uf76f\uf770\uf771\uf772\uf773\uf774\uf775\uf776\uf777\uf778\uf779\uf77a\uf77b\uf77c\uf77d\uf77e\uf77f\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff\uf800\uf801\uf802
 \uf803\uf804\uf805\uf806\uf807\uf808\uf809\uf80a\uf80b\uf80c\uf80d\uf80e\uf80f\uf810\uf811\uf812\uf813\uf814\uf815\uf816\uf817\uf818\uf819\uf81a\uf81b\uf81c\uf81d\uf81e\uf81f\uf820\uf821\uf822\uf823\uf824\uf825\uf826\uf827\uf828\uf829\uf82a\uf82b\uf82c\uf82d\uf82e\uf82f\uf830\uf831\uf832\uf833\uf834\uf835\uf836\uf837\uf838\uf839\uf83a\uf83b\uf83c\uf83d\uf83e\uf83f\uf840\uf841\uf842\uf843\uf844\uf845\uf846\uf847\uf848\uf849\uf84a\uf84b\uf84c\uf84d\uf84e\uf84f\uf850\uf851\uf852\uf853\uf854\uf855\uf856\uf857\uf858\uf859\uf85a\uf85b\uf85c\uf85d\uf85e\uf85f\uf860\uf861\uf862\uf863\uf864\uf865\uf866\uf867\uf868\uf869\uf86a\uf86b\uf86c\uf86d\uf86e\uf86f\uf870\uf871\uf872\uf873\uf874\uf875\uf876\uf877\uf878\uf879\uf87a\uf87b\uf87c\uf87d\uf87e\uf87f\uf880\uf881\uf882\uf883\uf884\uf885\uf886\uf887\uf888\uf889\uf88a\uf88b\uf88c\uf88d\uf88e\uf88f\uf890\uf891\uf892\uf893\uf894\uf895\uf896\uf897\uf898\uf899\uf89a\uf89b\uf89c\uf89d\uf89e\uf89f\uf8a0\uf8a1\uf8a2\uf8a3\uf8a4\uf8a5\uf8a6\uf8a7\uf8a8\
 uf8a9\uf8aa\uf8ab\uf8ac\uf8ad\uf8ae\uf8af\uf8b0\uf8b1\uf8b2\uf8b3\uf8b4\uf8b5\uf8b6\uf8b7\uf8b8\uf8b9\uf8ba\uf8bb\uf8bc\uf8bd\uf8be\uf8bf\uf8c0\uf8c1\uf8c2\uf8c3\uf8c4\uf8c5\uf8c6\uf8c7\uf8c8\uf8c9\uf8ca\uf8cb\uf8cc\uf8cd\uf8ce\uf8cf\uf8d0\uf8d1\uf8d2\uf8d3\uf8d4\uf8d5\uf8d6\uf8d7\uf8d8\uf8d9\uf8da\uf8db\uf8dc\uf8dd\uf8de\uf8df\uf8e0\uf8e1\uf8e2\uf8e3\uf8e4\uf8e5\uf8e6\uf8e7\uf8e8\uf8e9\uf8ea\uf8eb\uf8ec\uf8ed\uf8ee\uf8ef\uf8f0\uf8f1\uf8f2\uf8f3\uf8f4\uf8f5\uf8f6\uf8f7\uf8f8\uf8f9\uf8fa\uf8fb\uf8fc\uf8fd\uf8fe\uf8ff'
+
+try:
+    Cs = eval(r"'\ud800\ud801\ud802\ud803\ud804\ud805\ud806\ud807\ud808\ud809\ud80a\ud80b\ud80c\ud80d\ud80e\ud80f\ud810\ud811\ud812\ud813\ud814\ud815\ud816\ud817\ud818\ud819\ud81a\ud81b\ud81c\ud81d\ud81e\ud81f\ud820\ud821\ud822\ud823\ud824\ud825\ud826\ud827\ud828\ud829\ud82a\ud82b\ud82c\ud82d\ud82e\ud82f\ud830\ud831\ud832\ud833\ud834\ud835\ud836\ud837\ud838\ud839\ud83a\ud83b\ud83c\ud83d\ud83e\ud83f\ud840\ud841\ud842\ud843\ud844\ud845\ud846\ud847\ud848\ud849\ud84a\ud84b\ud84c\ud84d\ud84e\ud84f\ud850\ud851\ud852\ud853\ud854\ud855\ud856\ud857\ud858\ud859\ud85a\ud85b\ud85c\ud85d\ud85e\ud85f\ud860\ud861\ud862\ud863\ud864\ud865\ud866\ud867\ud868\ud869\ud86a\ud86b\ud86c\ud86d\ud86e\ud86f\ud870\ud871\ud872\ud873\ud874\ud875\ud876\ud877\ud878\ud879\ud87a\ud87b\ud87c\ud87d\ud87e\ud87f\ud880\ud881\ud882\ud883\ud884\ud885\ud886\ud887\ud888\ud889\ud88a\ud88b\ud88c\ud88d\ud88e\ud88f\ud890\ud891\ud892\ud893\ud894\ud895\ud896\ud897\ud898\ud899\ud89a\ud89b\ud89c\ud89d\ud89e\ud89f\ud8a0\ud8a1\ud8a2\u
 d8a3\ud8a4\ud8a5\ud8a6\ud8a7\ud8a8\ud8a9\ud8aa\ud8ab\ud8ac\ud8ad\ud8ae\ud8af\ud8b0\ud8b1\ud8b2\ud8b3\ud8b4\ud8b5\ud8b6\ud8b7\ud8b8\ud8b9\ud8ba\ud8bb\ud8bc\ud8bd\ud8be\ud8bf\ud8c0\ud8c1\ud8c2\ud8c3\ud8c4\ud8c5\ud8c6\ud8c7\ud8c8\ud8c9\ud8ca\ud8cb\ud8cc\ud8cd\ud8ce\ud8cf\ud8d0\ud8d1\ud8d2\ud8d3\ud8d4\ud8d5\ud8d6\ud8d7\ud8d8\ud8d9\ud8da\ud8db\ud8dc\ud8dd\ud8de\ud8df\ud8e0\ud8e1\ud8e2\ud8e3\ud8e4\ud8e5\ud8e6\ud8e7\ud8e8\ud8e9\ud8ea\ud8eb\ud8ec\ud8ed\ud8ee\ud8ef\ud8f0\ud8f1\ud8f2\ud8f3\ud8f4\ud8f5\ud8f6\ud8f7\ud8f8\ud8f9\ud8fa\ud8fb\ud8fc\ud8fd\ud8fe\ud8ff\ud900\ud901\ud902\ud903\ud904\ud905\ud906\ud907\ud908\ud909\ud90a\ud90b\ud90c\ud90d\ud90e\ud90f\ud910\ud911\ud912\ud913\ud914\ud915\ud916\ud917\ud918\ud919\ud91a\ud91b\ud91c\ud91d\ud91e\ud91f\ud920\ud921\ud922\ud923\ud924\ud925\ud926\ud927\ud928\ud929\ud92a\ud92b\ud92c\ud92d\ud92e\ud92f\ud930\ud931\ud932\ud933\ud934\ud935\ud936\ud937\ud938\ud939\ud93a\ud93b\ud93c\ud93d\ud93e\ud93f\ud940\ud941\ud942\ud943\ud944\ud945\ud946\ud947\ud948\ud
 949\ud94a\ud94b\ud94c\ud94d\ud94e\ud94f\ud950\ud951\ud952\ud953\ud954\ud955\ud956\ud957\ud958\ud959\ud95a\ud95b\ud95c\ud95d\ud95e\ud95f\ud960\ud961\ud962\ud963\ud964\ud965\ud966\ud967\ud968\ud969\ud96a\ud96b\ud96c\ud96d\ud96e\ud96f\ud970\ud971\ud972\ud973\ud974\ud975\ud976\ud977\ud978\ud979\ud97a\ud97b\ud97c\ud97d\ud97e\ud97f\ud980\ud981\ud982\ud983\ud984\ud985\ud986\ud987\ud988\ud989\ud98a\ud98b\ud98c\ud98d\ud98e\ud98f\ud990\ud991\ud992\ud993\ud994\ud995\ud996\ud997\ud998\ud999\ud99a\ud99b\ud99c\ud99d\ud99e\ud99f\ud9a0\ud9a1\ud9a2\ud9a3\ud9a4\ud9a5\ud9a6\ud9a7\ud9a8\ud9a9\ud9aa\ud9ab\ud9ac\ud9ad\ud9ae\ud9af\ud9b0\ud9b1\ud9b2\ud9b3\ud9b4\ud9b5\ud9b6\ud9b7\ud9b8\ud9b9\ud9ba\ud9bb\ud9bc\ud9bd\ud9be\ud9bf\ud9c0\ud9c1\ud9c2\ud9c3\ud9c4\ud9c5\ud9c6\ud9c7\ud9c8\ud9c9\ud9ca\ud9cb\ud9cc\ud9cd\ud9ce\ud9cf\ud9d0\ud9d1\ud9d2\ud9d3\ud9d4\ud9d5\ud9d6\ud9d7\ud9d8\ud9d9\ud9da\ud9db\ud9dc\ud9dd\ud9de\ud9df\ud9e0\ud9e1\ud9e2\ud9e3\ud9e4\ud9e5\ud9e6\ud9e7\ud9e8\ud9e9\ud9ea\ud9eb\ud9ec\ud9ed\ud9ee\ud9
 ef\ud9f0\ud9f1\ud9f2\ud9f3\ud9f4\ud9f5\ud9f6\ud9f7\ud9f8\ud9f9\ud9fa\ud9fb\ud9fc\ud9fd\ud9fe\ud9ff\uda00\uda01\uda02\uda03\uda04\uda05\uda06\uda07\uda08\uda09\uda0a\uda0b\uda0c\uda0d\uda0e\uda0f\uda10\uda11\uda12\uda13\uda14\uda15\uda16\uda17\uda18\uda19\uda1a\uda1b\uda1c\uda1d\uda1e\uda1f\uda20\uda21\uda22\uda23\uda24\uda25\uda26\uda27\uda28\uda29\uda2a\uda2b\uda2c\uda2d\uda2e\uda2f\uda30\uda31\uda32\uda33\uda34\uda35\uda36\uda37\uda38\uda39\uda3a\uda3b\uda3c\uda3d\uda3e\uda3f\uda40\uda41\uda42\uda43\uda44\uda45\uda46\uda47\uda48\uda49\uda4a\uda4b\uda4c\uda4d\uda4e\uda4f\uda50\uda51\uda52\uda53\uda54\uda55\uda56\uda57\uda58\uda59\uda5a\uda5b\uda5c\uda5d\uda5e\uda5f\uda60\uda61\uda62\uda63\uda64\uda65\uda66\uda67\uda68\uda69\uda6a\uda6b\uda6c\uda6d\uda6e\uda6f\uda70\uda71\uda72\uda73\uda74\uda75\uda76\uda77\uda78\uda79\uda7a\uda7b\uda7c\uda7d\uda7e\uda7f\uda80\uda81\uda82\uda83\uda84\uda85\uda86\uda87\uda88\uda89\uda8a\uda8b\uda8c\uda8d\uda8e\uda8f\uda90\uda91\uda92\uda93\uda94\uda9
 5\uda96\uda97\uda98\uda99\uda9a\uda9b\uda9c\uda9d\uda9e\uda9f\udaa0\udaa1\udaa2\udaa3\udaa4\udaa5\udaa6\udaa7\udaa8\udaa9\udaaa\udaab\udaac\udaad\udaae\udaaf\udab0\udab1\udab2\udab3\udab4\udab5\udab6\udab7\udab8\udab9\udaba\udabb\udabc\udabd\udabe\udabf\udac0\udac1\udac2\udac3\udac4\udac5\udac6\udac7\udac8\udac9\udaca\udacb\udacc\udacd\udace\udacf\udad0\udad1\udad2\udad3\udad4\udad5\udad6\udad7\udad8\udad9\udada\udadb\udadc\udadd\udade\udadf\udae0\udae1\udae2\udae3\udae4\udae5\udae6\udae7\udae8\udae9\udaea\udaeb\udaec\udaed\udaee\udaef\udaf0\udaf1\udaf2\udaf3\udaf4\udaf5\udaf6\udaf7\udaf8\udaf9\udafa\udafb\udafc\udafd\udafe\udaff\udb00\udb01\udb02\udb03\udb04\udb05\udb06\udb07\udb08\udb09\udb0a\udb0b\udb0c\udb0d\udb0e\udb0f\udb10\udb11\udb12\udb13\udb14\udb15\udb16\udb17\udb18\udb19\udb1a\udb1b\udb1c\udb1d\udb1e\udb1f\udb20\udb21\udb22\udb23\udb24\udb25\udb26\udb27\udb28\udb29\udb2a\udb2b\udb2c\udb2d\udb2e\udb2f\udb30\udb31\udb32\udb33\udb34\udb35\udb36\udb37\udb38\udb39\udb3a\udb3b
 \udb3c\udb3d\udb3e\udb3f\udb40\udb41\udb42\udb43\udb44\udb45\udb46\udb47\udb48\udb49\udb4a\udb4b\udb4c\udb4d\udb4e\udb4f\udb50\udb51\udb52\udb53\udb54\udb55\udb56\udb57\udb58\udb59\udb5a\udb5b\udb5c\udb5d\udb5e\udb5f\udb60\udb61\udb62\udb63\udb64\udb65\udb66\udb67\udb68\udb69\udb6a\udb6b\udb6c\udb6d\udb6e\udb6f\udb70\udb71\udb72\udb73\udb74\udb75\udb76\udb77\udb78\udb79\udb7a\udb7b\udb7c\udb7d\udb7e\udb7f\udb80\udb81\udb82\udb83\udb84\udb85\udb86\udb87\udb88\udb89\udb8a\udb8b\udb8c\udb8d\udb8e\udb8f\udb90\udb91\udb92\udb93\udb94\udb95\udb96\udb97\udb98\udb99\udb9a\udb9b\udb9c\udb9d\udb9e\udb9f\udba0\udba1\udba2\udba3\udba4\udba5\udba6\udba7\udba8\udba9\udbaa\udbab\udbac\udbad\udbae\udbaf\udbb0\udbb1\udbb2\udbb3\udbb4\udbb5\udbb6\udbb7\udbb8\udbb9\udbba\udbbb\udbbc\udbbd\udbbe\udbbf\udbc0\udbc1\udbc2\udbc3\udbc4\udbc5\udbc6\udbc7\udbc8\udbc9\udbca\udbcb\udbcc\udbcd\udbce\udbcf\udbd0\udbd1\udbd2\udbd3\udbd4\udbd5\udbd6\udbd7\udbd8\udbd9\udbda\udbdb\udbdc\udbdd\udbde\udbdf\udbe0\udbe1\
 udbe2\udbe3\udbe4\udbe5\udbe6\udbe7\udbe8\udbe9\udbea\udbeb\udbec\udbed\udbee\udbef\udbf0\udbf1\udbf2\udbf3\udbf4\udbf5\udbf6\udbf7\udbf8\udbf9\udbfa\udbfb\udbfc\udbfd\udbfe\U0010fc00\udc01\udc02\udc03\udc04\udc05\udc06\udc07\udc08\udc09\udc0a\udc0b\udc0c\udc0d\udc0e\udc0f\udc10\udc11\udc12\udc13\udc14\udc15\udc16\udc17\udc18\udc19\udc1a\udc1b\udc1c\udc1d\udc1e\udc1f\udc20\udc21\udc22\udc23\udc24\udc25\udc26\udc27\udc28\udc29\udc2a\udc2b\udc2c\udc2d\udc2e\udc2f\udc30\udc31\udc32\udc33\udc34\udc35\udc36\udc37\udc38\udc39\udc3a\udc3b\udc3c\udc3d\udc3e\udc3f\udc40\udc41\udc42\udc43\udc44\udc45\udc46\udc47\udc48\udc49\udc4a\udc4b\udc4c\udc4d\udc4e\udc4f\udc50\udc51\udc52\udc53\udc54\udc55\udc56\udc57\udc58\udc59\udc5a\udc5b\udc5c\udc5d\udc5e\udc5f\udc60\udc61\udc62\udc63\udc64\udc65\udc66\udc67\udc68\udc69\udc6a\udc6b\udc6c\udc6d\udc6e\udc6f\udc70\udc71\udc72\udc73\udc74\udc75\udc76\udc77\udc78\udc79\udc7a\udc7b\udc7c\udc7d\udc7e\udc7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc
 88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff\udd00\udd01\udd02\udd03\udd04\udd05\udd06\udd07\udd08\udd09\udd0a\udd0b\udd0c\udd0d\udd0e\udd0f\udd10\udd11\udd12\udd13\udd14\udd15\udd16\udd17\udd18\udd19\udd1a\udd1b\udd1c\udd1d\udd1e\udd1f\udd20\udd21\udd22\udd23\udd24\udd25\udd26\udd27\udd28\udd29\udd2a\udd2b\udd2c\udd2d\udd2
 e\udd2f\udd30\udd31\udd32\udd33\udd34\udd35\udd36\udd37\udd38\udd39\udd3a\udd3b\udd3c\udd3d\udd3e\udd3f\udd40\udd41\udd42\udd43\udd44\udd45\udd46\udd47\udd48\udd49\udd4a\udd4b\udd4c\udd4d\udd4e\udd4f\udd50\udd51\udd52\udd53\udd54\udd55\udd56\udd57\udd58\udd59\udd5a\udd5b\udd5c\udd5d\udd5e\udd5f\udd60\udd61\udd62\udd63\udd64\udd65\udd66\udd67\udd68\udd69\udd6a\udd6b\udd6c\udd6d\udd6e\udd6f\udd70\udd71\udd72\udd73\udd74\udd75\udd76\udd77\udd78\udd79\udd7a\udd7b\udd7c\udd7d\udd7e\udd7f\udd80\udd81\udd82\udd83\udd84\udd85\udd86\udd87\udd88\udd89\udd8a\udd8b\udd8c\udd8d\udd8e\udd8f\udd90\udd91\udd92\udd93\udd94\udd95\udd96\udd97\udd98\udd99\udd9a\udd9b\udd9c\udd9d\udd9e\udd9f\udda0\udda1\udda2\udda3\udda4\udda5\udda6\udda7\udda8\udda9\uddaa\uddab\uddac\uddad\uddae\uddaf\uddb0\uddb1\uddb2\uddb3\uddb4\uddb5\uddb6\uddb7\uddb8\uddb9\uddba\uddbb\uddbc\uddbd\uddbe\uddbf\uddc0\uddc1\uddc2\uddc3\uddc4\uddc5\uddc6\uddc7\uddc8\uddc9\uddca\uddcb\uddcc\uddcd\uddce\uddcf\uddd0\uddd1\uddd2\uddd3\uddd4
 \uddd5\uddd6\uddd7\uddd8\uddd9\uddda\udddb\udddc\udddd\uddde\udddf\udde0\udde1\udde2\udde3\udde4\udde5\udde6\udde7\udde8\udde9\uddea\uddeb\uddec\udded\uddee\uddef\uddf0\uddf1\uddf2\uddf3\uddf4\uddf5\uddf6\uddf7\uddf8\uddf9\uddfa\uddfb\uddfc\uddfd\uddfe\uddff\ude00\ude01\ude02\ude03\ude04\ude05\ude06\ude07\ude08\ude09\ude0a\ude0b\ude0c\ude0d\ude0e\ude0f\ude10\ude11\ude12\ude13\ude14\ude15\ude16\ude17\ude18\ude19\ude1a\ude1b\ude1c\ude1d\ude1e\ude1f\ude20\ude21\ude22\ude23\ude24\ude25\ude26\ude27\ude28\ude29\ude2a\ude2b\ude2c\ude2d\ude2e\ude2f\ude30\ude31\ude32\ude33\ude34\ude35\ude36\ude37\ude38\ude39\ude3a\ude3b\ude3c\ude3d\ude3e\ude3f\ude40\ude41\ude42\ude43\ude44\ude45\ude46\ude47\ude48\ude49\ude4a\ude4b\ude4c\ude4d\ude4e\ude4f\ude50\ude51\ude52\ude53\ude54\ude55\ude56\ude57\ude58\ude59\ude5a\ude5b\ude5c\ude5d\ude5e\ude5f\ude60\ude61\ude62\ude63\ude64\ude65\ude66\ude67\ude68\ude69\ude6a\ude6b\ude6c\ude6d\ude6e\ude6f\ude70\ude71\ude72\ude73\ude74\ude75\ude76\ude77\ude78\ude79\ude7a\
 ude7b\ude7c\ude7d\ude7e\ude7f\ude80\ude81\ude82\ude83\ude84\ude85\ude86\ude87\ude88\ude89\ude8a\ude8b\ude8c\ude8d\ude8e\ude8f\ude90\ude91\ude92\ude93\ude94\ude95\ude96\ude97\ude98\ude99\ude9a\ude9b\ude9c\ude9d\ude9e\ude9f\udea0\udea1\udea2\udea3\udea4\udea5\udea6\udea7\udea8\udea9\udeaa\udeab\udeac\udead\udeae\udeaf\udeb0\udeb1\udeb2\udeb3\udeb4\udeb5\udeb6\udeb7\udeb8\udeb9\udeba\udebb\udebc\udebd\udebe\udebf\udec0\udec1\udec2\udec3\udec4\udec5\udec6\udec7\udec8\udec9\udeca\udecb\udecc\udecd\udece\udecf\uded0\uded1\uded2\uded3\uded4\uded5\uded6\uded7\uded8\uded9\udeda\udedb\udedc\udedd\udede\udedf\udee0\udee1\udee2\udee3\udee4\udee5\udee6\udee7\udee8\udee9\udeea\udeeb\udeec\udeed\udeee\udeef\udef0\udef1\udef2\udef3\udef4\udef5\udef6\udef7\udef8\udef9\udefa\udefb\udefc\udefd\udefe\udeff\udf00\udf01\udf02\udf03\udf04\udf05\udf06\udf07\udf08\udf09\udf0a\udf0b\udf0c\udf0d\udf0e\udf0f\udf10\udf11\udf12\udf13\udf14\udf15\udf16\udf17\udf18\udf19\udf1a\udf1b\udf1c\udf1d\udf1e\udf1f\udf20\u
 df21\udf22\udf23\udf24\udf25\udf26\udf27\udf28\udf29\udf2a\udf2b\udf2c\udf2d\udf2e\udf2f\udf30\udf31\udf32\udf33\udf34\udf35\udf36\udf37\udf38\udf39\udf3a\udf3b\udf3c\udf3d\udf3e\udf3f\udf40\udf41\udf42\udf43\udf44\udf45\udf46\udf47\udf48\udf49\udf4a\udf4b\udf4c\udf4d\udf4e\udf4f\udf50\udf51\udf52\udf53\udf54\udf55\udf56\udf57\udf58\udf59\udf5a\udf5b\udf5c\udf5d\udf5e\udf5f\udf60\udf61\udf62\udf63\udf64\udf65\udf66\udf67\udf68\udf69\udf6a\udf6b\udf6c\udf6d\udf6e\udf6f\udf70\udf71\udf72\udf73\udf74\udf75\udf76\udf77\udf78\udf79\udf7a\udf7b\udf7c\udf7d\udf7e\udf7f\udf80\udf81\udf82\udf83\udf84\udf85\udf86\udf87\udf88\udf89\udf8a\udf8b\udf8c\udf8d\udf8e\udf8f\udf90\udf91\udf92\udf93\udf94\udf95\udf96\udf97\udf98\udf99\udf9a\udf9b\udf9c\udf9d\udf9e\udf9f\udfa0\udfa1\udfa2\udfa3\udfa4\udfa5\udfa6\udfa7\udfa8\udfa9\udfaa\udfab\udfac\udfad\udfae\udfaf\udfb0\udfb1\udfb2\udfb3\udfb4\udfb5\udfb6\udfb7\udfb8\udfb9\udfba\udfbb\udfbc\udfbd\udfbe\udfbf\udfc0\udfc1\udfc2\udfc3\udfc4\udfc5\udfc6\ud
 fc7\udfc8\udfc9\udfca\udfcb\udfcc\udfcd\udfce\udfcf\udfd0\udfd1\udfd2\udfd3\udfd4\udfd5\udfd6\udfd7\udfd8\udfd9\udfda\udfdb\udfdc\udfdd\udfde\udfdf\udfe0\udfe1\udfe2\udfe3\udfe4\udfe5\udfe6\udfe7\udfe8\udfe9\udfea\udfeb\udfec\udfed\udfee\udfef\udff0\udff1\udff2\udff3\udff4\udff5\udff6\udff7\udff8\udff9\udffa\udffb\udffc\udffd\udffe\udfff'")
+except UnicodeDecodeError:
+    Cs = '' # Jython can't handle isolated surrogates
+
+Ll = u'abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u
 0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u0234\u0235\u0236\u0237\u0238\u0239\u023c\u023f\u0240\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d\u028e\u028f\u0290\u0291\u0292\u0293\u0294\u0295\u0296\u0297\u0298\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac\u02ad\u02ae\u02af\u0390\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u0
 3ef\u03f0\u03f1\u03f2\u03f3\u03f5\u03f8\u03fb\u03fc\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0561\u0562\u0563\u0564\u0565\u0566\u0567\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b\u057c\u057d\u05
 7e\u057f\u0580\u0581\u0582\u0583\u0584\u0585\u0586\u0587\u1d00\u1d01\u1d02\u1d03\u1d04\u1d05\u1d06\u1d07\u1d08\u1d09\u1d0a\u1d0b\u1d0c\u1d0d\u1d0e\u1d0f\u1d10\u1d11\u1d12\u1d13\u1d14\u1d15\u1d16\u1d17\u1d18\u1d19\u1d1a\u1d1b\u1d1c\u1d1d\u1d1e\u1d1f\u1d20\u1d21\u1d22\u1d23\u1d24\u1d25\u1d26\u1d27\u1d28\u1d29\u1d2a\u1d2b\u1d62\u1d63\u1d64\u1d65\u1d66\u1d67\u1d68\u1d69\u1d6a\u1d6b\u1d6c\u1d6d\u1d6e\u1d6f\u1d70\u1d71\u1d72\u1d73\u1d74\u1d75\u1d76\u1d77\u1d79\u1d7a\u1d7b\u1d7c\u1d7d\u1d7e\u1d7f\u1d80\u1d81\u1d82\u1d83\u1d84\u1d85\u1d86\u1d87\u1d88\u1d89\u1d8a\u1d8b\u1d8c\u1d8d\u1d8e\u1d8f\u1d90\u1d91\u1d92\u1d93\u1d94\u1d95\u1d96\u1d97\u1d98\u1d99\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e7
 1\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98\u1e99\u1e9a\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6\u1fb7
 \u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1ff7\u2071\u207f\u210a\u210e\u210f\u2113\u212f\u2134\u2139\u213c\u21

<TRUNCATED>

[46/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py
new file mode 100644
index 0000000..804070c
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/nodes.py
@@ -0,0 +1,901 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.nodes
+    ~~~~~~~~~~~~
+
+    This module implements additional nodes derived from the ast base node.
+
+    It also provides some node tree helper functions like `in_lineno` and
+    `get_nodes` used by the parser and translator in order to normalize
+    python and jinja nodes.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import operator
+from itertools import chain, izip
+from collections import deque
+from ambari_jinja2.utils import Markup, MethodType, FunctionType
+
+
+#: the types we support for context functions
+_context_function_types = (FunctionType, MethodType)
+
+
+_binop_to_func = {
+    '*':        operator.mul,
+    '/':        operator.truediv,
+    '//':       operator.floordiv,
+    '**':       operator.pow,
+    '%':        operator.mod,
+    '+':        operator.add,
+    '-':        operator.sub
+}
+
+_uaop_to_func = {
+    'not':      operator.not_,
+    '+':        operator.pos,
+    '-':        operator.neg
+}
+
+_cmpop_to_func = {
+    'eq':       operator.eq,
+    'ne':       operator.ne,
+    'gt':       operator.gt,
+    'gteq':     operator.ge,
+    'lt':       operator.lt,
+    'lteq':     operator.le,
+    'in':       lambda a, b: a in b,
+    'notin':    lambda a, b: a not in b
+}
+
+
+class Impossible(Exception):
+    """Raised if the node could not perform a requested action."""
+
+
+class NodeType(type):
+    """A metaclass for nodes that handles the field and attribute
+    inheritance.  fields and attributes from the parent class are
+    automatically forwarded to the child."""
+
+    def __new__(cls, name, bases, d):
+        for attr in 'fields', 'attributes':
+            storage = []
+            storage.extend(getattr(bases[0], attr, ()))
+            storage.extend(d.get(attr, ()))
+            assert len(bases) == 1, 'multiple inheritance not allowed'
+            assert len(storage) == len(set(storage)), 'layout conflict'
+            d[attr] = tuple(storage)
+        d.setdefault('abstract', False)
+        return type.__new__(cls, name, bases, d)
+
+
+class EvalContext(object):
+    """Holds evaluation time information.  Custom attributes can be attached
+    to it in extensions.
+    """
+
+    def __init__(self, environment, template_name=None):
+        if callable(environment.autoescape):
+            self.autoescape = environment.autoescape(template_name)
+        else:
+            self.autoescape = environment.autoescape
+        self.volatile = False
+
+    def save(self):
+        return self.__dict__.copy()
+
+    def revert(self, old):
+        self.__dict__.clear()
+        self.__dict__.update(old)
+
+
+def get_eval_context(node, ctx):
+    if ctx is None:
+        if node.environment is None:
+            raise RuntimeError('if no eval context is passed, the '
+                               'node must have an attached '
+                               'environment.')
+        return EvalContext(node.environment)
+    return ctx
+
+
+class Node(object):
+    """Baseclass for all Jinja2 nodes.  There are a number of nodes available
+    of different types.  There are three major types:
+
+    -   :class:`Stmt`: statements
+    -   :class:`Expr`: expressions
+    -   :class:`Helper`: helper nodes
+    -   :class:`Template`: the outermost wrapper node
+
+    All nodes have fields and attributes.  Fields may be other nodes, lists,
+    or arbitrary values.  Fields are passed to the constructor as regular
+    positional arguments, attributes as keyword arguments.  Each node has
+    two attributes: `lineno` (the line number of the node) and `environment`.
+    The `environment` attribute is set at the end of the parsing process for
+    all nodes automatically.
+    """
+    __metaclass__ = NodeType
+    fields = ()
+    attributes = ('lineno', 'environment')
+    abstract = True
+
+    def __init__(self, *fields, **attributes):
+        if self.abstract:
+            raise TypeError('abstract nodes are not instanciable')
+        if fields:
+            if len(fields) != len(self.fields):
+                if not self.fields:
+                    raise TypeError('%r takes 0 arguments' %
+                                    self.__class__.__name__)
+                raise TypeError('%r takes 0 or %d argument%s' % (
+                    self.__class__.__name__,
+                    len(self.fields),
+                    len(self.fields) != 1 and 's' or ''
+                ))
+            for name, arg in izip(self.fields, fields):
+                setattr(self, name, arg)
+        for attr in self.attributes:
+            setattr(self, attr, attributes.pop(attr, None))
+        if attributes:
+            raise TypeError('unknown attribute %r' %
+                            iter(attributes).next())
+
+    def iter_fields(self, exclude=None, only=None):
+        """This method iterates over all fields that are defined and yields
+        ``(key, value)`` tuples.  Per default all fields are returned, but
+        it's possible to limit that to some fields by providing the `only`
+        parameter or to exclude some using the `exclude` parameter.  Both
+        should be sets or tuples of field names.
+        """
+        for name in self.fields:
+            if (exclude is only is None) or \
+               (exclude is not None and name not in exclude) or \
+               (only is not None and name in only):
+                try:
+                    yield name, getattr(self, name)
+                except AttributeError:
+                    pass
+
+    def iter_child_nodes(self, exclude=None, only=None):
+        """Iterates over all direct child nodes of the node.  This iterates
+        over all fields and yields the values of they are nodes.  If the value
+        of a field is a list all the nodes in that list are returned.
+        """
+        for field, item in self.iter_fields(exclude, only):
+            if isinstance(item, list):
+                for n in item:
+                    if isinstance(n, Node):
+                        yield n
+            elif isinstance(item, Node):
+                yield item
+
+    def find(self, node_type):
+        """Find the first node of a given type.  If no such node exists the
+        return value is `None`.
+        """
+        for result in self.find_all(node_type):
+            return result
+
+    def find_all(self, node_type):
+        """Find all the nodes of a given type.  If the type is a tuple,
+        the check is performed for any of the tuple items.
+        """
+        for child in self.iter_child_nodes():
+            if isinstance(child, node_type):
+                yield child
+            for result in child.find_all(node_type):
+                yield result
+
+    def set_ctx(self, ctx):
+        """Reset the context of a node and all child nodes.  Per default the
+        parser will all generate nodes that have a 'load' context as it's the
+        most common one.  This method is used in the parser to set assignment
+        targets and other nodes to a store context.
+        """
+        todo = deque([self])
+        while todo:
+            node = todo.popleft()
+            if 'ctx' in node.fields:
+                node.ctx = ctx
+            todo.extend(node.iter_child_nodes())
+        return self
+
+    def set_lineno(self, lineno, override=False):
+        """Set the line numbers of the node and children."""
+        todo = deque([self])
+        while todo:
+            node = todo.popleft()
+            if 'lineno' in node.attributes:
+                if node.lineno is None or override:
+                    node.lineno = lineno
+            todo.extend(node.iter_child_nodes())
+        return self
+
+    def set_environment(self, environment):
+        """Set the environment for all nodes."""
+        todo = deque([self])
+        while todo:
+            node = todo.popleft()
+            node.environment = environment
+            todo.extend(node.iter_child_nodes())
+        return self
+
+    def __eq__(self, other):
+        return type(self) is type(other) and \
+               tuple(self.iter_fields()) == tuple(other.iter_fields())
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
+                      arg in self.fields)
+        )
+
+
+class Stmt(Node):
+    """Base node for all statements."""
+    abstract = True
+
+
+class Helper(Node):
+    """Nodes that exist in a specific context only."""
+    abstract = True
+
+
+class Template(Node):
+    """Node that represents a template.  This must be the outermost node that
+    is passed to the compiler.
+    """
+    fields = ('body',)
+
+
+class Output(Stmt):
+    """A node that holds multiple expressions which are then printed out.
+    This is used both for the `print` statement and the regular template data.
+    """
+    fields = ('nodes',)
+
+
+class Extends(Stmt):
+    """Represents an extends statement."""
+    fields = ('template',)
+
+
+class For(Stmt):
+    """The for loop.  `target` is the target for the iteration (usually a
+    :class:`Name` or :class:`Tuple`), `iter` the iterable.  `body` is a list
+    of nodes that are used as loop-body, and `else_` a list of nodes for the
+    `else` block.  If no else node exists it has to be an empty list.
+
+    For filtered nodes an expression can be stored as `test`, otherwise `None`.
+    """
+    fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive')
+
+
+class If(Stmt):
+    """If `test` is true, `body` is rendered, else `else_`."""
+    fields = ('test', 'body', 'else_')
+
+
+class Macro(Stmt):
+    """A macro definition.  `name` is the name of the macro, `args` a list of
+    arguments and `defaults` a list of defaults if there are any.  `body` is
+    a list of nodes for the macro body.
+    """
+    fields = ('name', 'args', 'defaults', 'body')
+
+
+class CallBlock(Stmt):
+    """Like a macro without a name but a call instead.  `call` is called with
+    the unnamed macro as `caller` argument this node holds.
+    """
+    fields = ('call', 'args', 'defaults', 'body')
+
+
+class FilterBlock(Stmt):
+    """Node for filter sections."""
+    fields = ('body', 'filter')
+
+
+class Block(Stmt):
+    """A node that represents a block."""
+    fields = ('name', 'body', 'scoped')
+
+
+class Include(Stmt):
+    """A node that represents the include tag."""
+    fields = ('template', 'with_context', 'ignore_missing')
+
+
+class Import(Stmt):
+    """A node that represents the import tag."""
+    fields = ('template', 'target', 'with_context')
+
+
+class FromImport(Stmt):
+    """A node that represents the from import tag.  It's important to not
+    pass unsafe names to the name attribute.  The compiler translates the
+    attribute lookups directly into getattr calls and does *not* use the
+    subscript callback of the interface.  As exported variables may not
+    start with double underscores (which the parser asserts) this is not a
+    problem for regular Jinja code, but if this node is used in an extension
+    extra care must be taken.
+
+    The list of names may contain tuples if aliases are wanted.
+    """
+    fields = ('template', 'names', 'with_context')
+
+
+class ExprStmt(Stmt):
+    """A statement that evaluates an expression and discards the result."""
+    fields = ('node',)
+
+
+class Assign(Stmt):
+    """Assigns an expression to a target."""
+    fields = ('target', 'node')
+
+
+class Expr(Node):
+    """Baseclass for all expressions."""
+    abstract = True
+
+    def as_const(self, eval_ctx=None):
+        """Return the value of the expression as constant or raise
+        :exc:`Impossible` if this was not possible.
+
+        An :class:`EvalContext` can be provided, if none is given
+        a default context is created which requires the nodes to have
+        an attached environment.
+
+        .. versionchanged:: 2.4
+           the `eval_ctx` parameter was added.
+        """
+        raise Impossible()
+
+    def can_assign(self):
+        """Check if it's possible to assign something to this node."""
+        return False
+
+
+class BinExpr(Expr):
+    """Baseclass for all binary expressions."""
+    fields = ('left', 'right')
+    operator = None
+    abstract = True
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        f = _binop_to_func[self.operator]
+        try:
+            return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx))
+        except:
+            raise Impossible()
+
+
+class UnaryExpr(Expr):
+    """Baseclass for all unary expressions."""
+    fields = ('node',)
+    operator = None
+    abstract = True
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        f = _uaop_to_func[self.operator]
+        try:
+            return f(self.node.as_const(eval_ctx))
+        except:
+            raise Impossible()
+
+
+class Name(Expr):
+    """Looks up a name or stores a value in a name.
+    The `ctx` of the node can be one of the following values:
+
+    -   `store`: store a value in the name
+    -   `load`: load that name
+    -   `param`: like `store` but if the name was defined as function parameter.
+    """
+    fields = ('name', 'ctx')
+
+    def can_assign(self):
+        return self.name not in ('true', 'false', 'none',
+                                 'True', 'False', 'None')
+
+
+class Literal(Expr):
+    """Baseclass for literals."""
+    abstract = True
+
+
+class Const(Literal):
+    """All constant values.  The parser will return this node for simple
+    constants such as ``42`` or ``"foo"`` but it can be used to store more
+    complex values such as lists too.  Only constants with a safe
+    representation (objects where ``eval(repr(x)) == x`` is true).
+    """
+    fields = ('value',)
+
+    def as_const(self, eval_ctx=None):
+        return self.value
+
+    @classmethod
+    def from_untrusted(cls, value, lineno=None, environment=None):
+        """Return a const object if the value is representable as
+        constant value in the generated code, otherwise it will raise
+        an `Impossible` exception.
+        """
+        from compiler import has_safe_repr
+        if not has_safe_repr(value):
+            raise Impossible()
+        return cls(value, lineno=lineno, environment=environment)
+
+
+class TemplateData(Literal):
+    """A constant template string."""
+    fields = ('data',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile:
+            raise Impossible()
+        if eval_ctx.autoescape:
+            return Markup(self.data)
+        return self.data
+
+
+class Tuple(Literal):
+    """For loop unpacking and some other things like multiple arguments
+    for subscripts.  Like for :class:`Name` `ctx` specifies if the tuple
+    is used for loading the names or storing.
+    """
+    fields = ('items', 'ctx')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return tuple(x.as_const(eval_ctx) for x in self.items)
+
+    def can_assign(self):
+        for item in self.items:
+            if not item.can_assign():
+                return False
+        return True
+
+
+class List(Literal):
+    """Any list literal such as ``[1, 2, 3]``"""
+    fields = ('items',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return [x.as_const(eval_ctx) for x in self.items]
+
+
+class Dict(Literal):
+    """Any dict literal such as ``{1: 2, 3: 4}``.  The items must be a list of
+    :class:`Pair` nodes.
+    """
+    fields = ('items',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return dict(x.as_const(eval_ctx) for x in self.items)
+
+
+class Pair(Helper):
+    """A key, value pair for dicts."""
+    fields = ('key', 'value')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
+
+
+class Keyword(Helper):
+    """A key, value pair for keyword arguments where key is a string."""
+    fields = ('key', 'value')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.key, self.value.as_const(eval_ctx)
+
+
+class CondExpr(Expr):
+    """A conditional expression (inline if expression).  (``{{
+    foo if bar else baz }}``)
+    """
+    fields = ('test', 'expr1', 'expr2')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if self.test.as_const(eval_ctx):
+            return self.expr1.as_const(eval_ctx)
+
+        # if we evaluate to an undefined object, we better do that at runtime
+        if self.expr2 is None:
+            raise Impossible()
+
+        return self.expr2.as_const(eval_ctx)
+
+
+class Filter(Expr):
+    """This node applies a filter on an expression.  `name` is the name of
+    the filter, the rest of the fields are the same as for :class:`Call`.
+
+    If the `node` of a filter is `None` the contents of the last buffer are
+    filtered.  Buffers are created by macros and filter blocks.
+    """
+    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile or self.node is None:
+            raise Impossible()
+        # we have to be careful here because we call filter_ below.
+        # if this variable would be called filter, 2to3 would wrap the
+        # call in a list beause it is assuming we are talking about the
+        # builtin filter function here which no longer returns a list in
+        # python 3.  because of that, do not rename filter_ to filter!
+        filter_ = self.environment.filters.get(self.name)
+        if filter_ is None or getattr(filter_, 'contextfilter', False):
+            raise Impossible()
+        obj = self.node.as_const(eval_ctx)
+        args = [x.as_const(eval_ctx) for x in self.args]
+        if getattr(filter_, 'evalcontextfilter', False):
+            args.insert(0, eval_ctx)
+        elif getattr(filter_, 'environmentfilter', False):
+            args.insert(0, self.environment)
+        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
+        if self.dyn_args is not None:
+            try:
+                args.extend(self.dyn_args.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        if self.dyn_kwargs is not None:
+            try:
+                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        try:
+            return filter_(obj, *args, **kwargs)
+        except:
+            raise Impossible()
+
+
+class Test(Expr):
+    """Applies a test on an expression.  `name` is the name of the test, the
+    rest of the fields are the same as for :class:`Call`.
+    """
+    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+
+class Call(Expr):
+    """Calls an expression.  `args` is a list of arguments, `kwargs` a list
+    of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
+    and `dyn_kwargs` has to be either `None` or a node that is used as
+    node for dynamic positional (``*args``) or keyword (``**kwargs``)
+    arguments.
+    """
+    fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile:
+            raise Impossible()
+        obj = self.node.as_const(eval_ctx)
+
+        # don't evaluate context functions
+        args = [x.as_const(eval_ctx) for x in self.args]
+        if isinstance(obj, _context_function_types):
+            if getattr(obj, 'contextfunction', False):
+                raise Impossible()
+            elif getattr(obj, 'evalcontextfunction', False):
+                args.insert(0, eval_ctx)
+            elif getattr(obj, 'environmentfunction', False):
+                args.insert(0, self.environment)
+
+        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
+        if self.dyn_args is not None:
+            try:
+                args.extend(self.dyn_args.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        if self.dyn_kwargs is not None:
+            try:
+                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        try:
+            return obj(*args, **kwargs)
+        except:
+            raise Impossible()
+
+
+class Getitem(Expr):
+    """Get an attribute or item from an expression and prefer the item."""
+    fields = ('node', 'arg', 'ctx')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if self.ctx != 'load':
+            raise Impossible()
+        try:
+            return self.environment.getitem(self.node.as_const(eval_ctx),
+                                            self.arg.as_const(eval_ctx))
+        except:
+            raise Impossible()
+
+    def can_assign(self):
+        return False
+
+
+class Getattr(Expr):
+    """Get an attribute or item from an expression that is a ascii-only
+    bytestring and prefer the attribute.
+    """
+    fields = ('node', 'attr', 'ctx')
+
+    def as_const(self, eval_ctx=None):
+        if self.ctx != 'load':
+            raise Impossible()
+        try:
+            eval_ctx = get_eval_context(self, eval_ctx)
+            return self.environment.getattr(self.node.as_const(eval_ctx),
+                                            self.attr)
+        except:
+            raise Impossible()
+
+    def can_assign(self):
+        return False
+
+
+class Slice(Expr):
+    """Represents a slice object.  This must only be used as argument for
+    :class:`Subscript`.
+    """
+    fields = ('start', 'stop', 'step')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        def const(obj):
+            if obj is None:
+                return None
+            return obj.as_const(eval_ctx)
+        return slice(const(self.start), const(self.stop), const(self.step))
+
+
+class Concat(Expr):
+    """Concatenates the list of expressions provided after converting them to
+    unicode.
+    """
+    fields = ('nodes',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes)
+
+
+class Compare(Expr):
+    """Compares an expression with some other expressions.  `ops` must be a
+    list of :class:`Operand`\s.
+    """
+    fields = ('expr', 'ops')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        result = value = self.expr.as_const(eval_ctx)
+        try:
+            for op in self.ops:
+                new_value = op.expr.as_const(eval_ctx)
+                result = _cmpop_to_func[op.op](value, new_value)
+                value = new_value
+        except:
+            raise Impossible()
+        return result
+
+
+class Operand(Helper):
+    """Holds an operator and an expression."""
+    fields = ('op', 'expr')
+
+if __debug__:
+    Operand.__doc__ += '\nThe following operators are available: ' + \
+        ', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
+                  set(_uaop_to_func) | set(_cmpop_to_func)))
+
+
+class Mul(BinExpr):
+    """Multiplies the left with the right node."""
+    operator = '*'
+
+
+class Div(BinExpr):
+    """Divides the left by the right node."""
+    operator = '/'
+
+
+class FloorDiv(BinExpr):
+    """Divides the left by the right node and truncates conver the
+    result into an integer by truncating.
+    """
+    operator = '//'
+
+
+class Add(BinExpr):
+    """Add the left to the right node."""
+    operator = '+'
+
+
+class Sub(BinExpr):
+    """Substract the right from the left node."""
+    operator = '-'
+
+
+class Mod(BinExpr):
+    """Left modulo right."""
+    operator = '%'
+
+
+class Pow(BinExpr):
+    """Left to the power of right."""
+    operator = '**'
+
+
+class And(BinExpr):
+    """Short circuited AND."""
+    operator = 'and'
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx)
+
+
+class Or(BinExpr):
+    """Short circuited OR."""
+    operator = 'or'
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx)
+
+
+class Not(UnaryExpr):
+    """Negate the expression."""
+    operator = 'not'
+
+
+class Neg(UnaryExpr):
+    """Make the expression negative."""
+    operator = '-'
+
+
+class Pos(UnaryExpr):
+    """Make the expression positive (noop for most expressions)"""
+    operator = '+'
+
+
+# Helpers for extensions
+
+
+class EnvironmentAttribute(Expr):
+    """Loads an attribute from the environment object.  This is useful for
+    extensions that want to call a callback stored on the environment.
+    """
+    fields = ('name',)
+
+
+class ExtensionAttribute(Expr):
+    """Returns the attribute of an extension bound to the environment.
+    The identifier is the identifier of the :class:`Extension`.
+
+    This node is usually constructed by calling the
+    :meth:`~ambari_jinja2.ext.Extension.attr` method on an extension.
+    """
+    fields = ('identifier', 'name')
+
+
+class ImportedName(Expr):
+    """If created with an import name the import name is returned on node
+    access.  For example ``ImportedName('cgi.escape')`` returns the `escape`
+    function from the cgi module on evaluation.  Imports are optimized by the
+    compiler so there is no need to assign them to local variables.
+    """
+    fields = ('importname',)
+
+
+class InternalName(Expr):
+    """An internal name in the compiler.  You cannot create these nodes
+    yourself but the parser provides a
+    :meth:`~ambari_jinja2.parser.Parser.free_identifier` method that creates
+    a new identifier for you.  This identifier is not available from the
+    template and is not threated specially by the compiler.
+    """
+    fields = ('name',)
+
+    def __init__(self):
+        raise TypeError('Can\'t create internal names.  Use the '
+                        '`free_identifier` method on a parser.')
+
+
+class MarkSafe(Expr):
+    """Mark the wrapped expression as safe (wrap it as `Markup`)."""
+    fields = ('expr',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return Markup(self.expr.as_const(eval_ctx))
+
+
+class MarkSafeIfAutoescape(Expr):
+    """Mark the wrapped expression as safe (wrap it as `Markup`) but
+    only if autoescaping is active.
+
+    .. versionadded:: 2.5
+    """
+    fields = ('expr',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile:
+            raise Impossible()
+        expr = self.expr.as_const(eval_ctx)
+        if eval_ctx.autoescape:
+            return Markup(expr)
+        return expr
+
+
+class ContextReference(Expr):
+    """Returns the current template context.  It can be used like a
+    :class:`Name` node, with a ``'load'`` ctx and will return the
+    current :class:`~ambari_jinja2.runtime.Context` object.
+
+    Here an example that assigns the current template name to a
+    variable named `foo`::
+
+        Assign(Name('foo', ctx='store'),
+               Getattr(ContextReference(), 'name'))
+    """
+
+
+class Continue(Stmt):
+    """Continue a loop."""
+
+
+class Break(Stmt):
+    """Break a loop."""
+
+
+class Scope(Stmt):
+    """An artificial scope."""
+    fields = ('body',)
+
+
+class EvalContextModifier(Stmt):
+    """Modifies the eval context.  For each option that should be modified,
+    a :class:`Keyword` has to be added to the :attr:`options` list.
+
+    Example to change the `autoescape` setting::
+
+        EvalContextModifier(options=[Keyword('autoescape', Const(True))])
+    """
+    fields = ('options',)
+
+
+class ScopedEvalContextModifier(EvalContextModifier):
+    """Modifies the eval context and reverts it later.  Works exactly like
+    :class:`EvalContextModifier` but will only modify the
+    :class:`~ambari_jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
+    """
+    fields = ('body',)
+
+
+# make sure nobody creates custom nodes
+def _failing_new(*args, **kwargs):
+    raise TypeError('can\'t create custom node types')
+NodeType.__new__ = staticmethod(_failing_new); del _failing_new

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py
new file mode 100644
index 0000000..b014396
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/optimizer.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.optimizer
+    ~~~~~~~~~~~~~~~~
+
+    The jinja optimizer is currently trying to constant fold a few expressions
+    and modify the AST in place so that it should be easier to evaluate it.
+
+    Because the AST does not contain all the scoping information and the
+    compiler has to find that out, we cannot do all the optimizations we
+    want.  For example loop unrolling doesn't work because unrolled loops would
+    have a different scoping.
+
+    The solution would be a second syntax tree that has the scoping rules stored.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from ambari_jinja2 import nodes
+from ambari_jinja2.visitor import NodeTransformer
+
+
+def optimize(node, environment):
+    """The context hint can be used to perform an static optimization
+    based on the context given."""
+    optimizer = Optimizer(environment)
+    return optimizer.visit(node)
+
+
+class Optimizer(NodeTransformer):
+
+    def __init__(self, environment):
+        self.environment = environment
+
+    def visit_If(self, node):
+        """Eliminate dead code."""
+        # do not optimize ifs that have a block inside so that it doesn't
+        # break super().
+        if node.find(nodes.Block) is not None:
+            return self.generic_visit(node)
+        try:
+            val = self.visit(node.test).as_const()
+        except nodes.Impossible:
+            return self.generic_visit(node)
+        if val:
+            body = node.body
+        else:
+            body = node.else_
+        result = []
+        for node in body:
+            result.extend(self.visit_list(node))
+        return result
+
+    def fold(self, node):
+        """Do constant folding."""
+        node = self.generic_visit(node)
+        try:
+            return nodes.Const.from_untrusted(node.as_const(),
+                                              lineno=node.lineno,
+                                              environment=self.environment)
+        except nodes.Impossible:
+            return node
+
+    visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
+    visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
+    visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \
+    visit_Filter = visit_Test = visit_CondExpr = fold
+    del fold

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py
new file mode 100644
index 0000000..a14c055
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/parser.py
@@ -0,0 +1,896 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.parser
+    ~~~~~~~~~~~~~
+
+    Implements the template parser.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from ambari_jinja2 import nodes
+from ambari_jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
+from ambari_jinja2.utils import next
+from ambari_jinja2.lexer import describe_token, describe_token_expr
+
+
+#: statements that callinto 
+_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
+                                 'macro', 'include', 'from', 'import',
+                                 'set'])
+_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
+
+
+class Parser(object):
+    """This is the central parsing class Jinja2 uses.  It's passed to
+    extensions and can be used to parse expressions or statements.
+    """
+
+    def __init__(self, environment, source, name=None, filename=None,
+                 state=None):
+        self.environment = environment
+        self.stream = environment._tokenize(source, name, filename, state)
+        self.name = name
+        self.filename = filename
+        self.closed = False
+        self.extensions = {}
+        for extension in environment.iter_extensions():
+            for tag in extension.tags:
+                self.extensions[tag] = extension.parse
+        self._last_identifier = 0
+        self._tag_stack = []
+        self._end_token_stack = []
+
+    def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
+        """Convenience method that raises `exc` with the message, passed
+        line number or last line number as well as the current name and
+        filename.
+        """
+        if lineno is None:
+            lineno = self.stream.current.lineno
+        raise exc(msg, lineno, self.name, self.filename)
+
+    def _fail_ut_eof(self, name, end_token_stack, lineno):
+        expected = []
+        for exprs in end_token_stack:
+            expected.extend(map(describe_token_expr, exprs))
+        if end_token_stack:
+            currently_looking = ' or '.join(
+                "'%s'" % describe_token_expr(expr)
+                for expr in end_token_stack[-1])
+        else:
+            currently_looking = None
+
+        if name is None:
+            message = ['Unexpected end of template.']
+        else:
+            message = ['Encountered unknown tag \'%s\'.' % name]
+
+        if currently_looking:
+            if name is not None and name in expected:
+                message.append('You probably made a nesting mistake. Jinja '
+                               'is expecting this tag, but currently looking '
+                               'for %s.' % currently_looking)
+            else:
+                message.append('Jinja was looking for the following tags: '
+                               '%s.' % currently_looking)
+
+        if self._tag_stack:
+            message.append('The innermost block that needs to be '
+                           'closed is \'%s\'.' % self._tag_stack[-1])
+
+        self.fail(' '.join(message), lineno)
+
+    def fail_unknown_tag(self, name, lineno=None):
+        """Called if the parser encounters an unknown tag.  Tries to fail
+        with a human readable error message that could help to identify
+        the problem.
+        """
+        return self._fail_ut_eof(name, self._end_token_stack, lineno)
+
+    def fail_eof(self, end_tokens=None, lineno=None):
+        """Like fail_unknown_tag but for end of template situations."""
+        stack = list(self._end_token_stack)
+        if end_tokens is not None:
+            stack.append(end_tokens)
+        return self._fail_ut_eof(None, stack, lineno)
+
+    def is_tuple_end(self, extra_end_rules=None):
+        """Are we at the end of a tuple?"""
+        if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
+            return True
+        elif extra_end_rules is not None:
+            return self.stream.current.test_any(extra_end_rules)
+        return False
+
+    def free_identifier(self, lineno=None):
+        """Return a new free identifier as :class:`~ambari_jinja2.nodes.InternalName`."""
+        self._last_identifier += 1
+        rv = object.__new__(nodes.InternalName)
+        nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
+        return rv
+
+    def parse_statement(self):
+        """Parse a single statement."""
+        token = self.stream.current
+        if token.type != 'name':
+            self.fail('tag name expected', token.lineno)
+        self._tag_stack.append(token.value)
+        pop_tag = True
+        try:
+            if token.value in _statement_keywords:
+                return getattr(self, 'parse_' + self.stream.current.value)()
+            if token.value == 'call':
+                return self.parse_call_block()
+            if token.value == 'filter':
+                return self.parse_filter_block()
+            ext = self.extensions.get(token.value)
+            if ext is not None:
+                return ext(self)
+
+            # did not work out, remove the token we pushed by accident
+            # from the stack so that the unknown tag fail function can
+            # produce a proper error message.
+            self._tag_stack.pop()
+            pop_tag = False
+            self.fail_unknown_tag(token.value, token.lineno)
+        finally:
+            if pop_tag:
+                self._tag_stack.pop()
+
+    def parse_statements(self, end_tokens, drop_needle=False):
+        """Parse multiple statements into a list until one of the end tokens
+        is reached.  This is used to parse the body of statements as it also
+        parses template data if appropriate.  The parser checks first if the
+        current token is a colon and skips it if there is one.  Then it checks
+        for the block end and parses until if one of the `end_tokens` is
+        reached.  Per default the active token in the stream at the end of
+        the call is the matched end token.  If this is not wanted `drop_needle`
+        can be set to `True` and the end token is removed.
+        """
+        # the first token may be a colon for python compatibility
+        self.stream.skip_if('colon')
+
+        # in the future it would be possible to add whole code sections
+        # by adding some sort of end of statement token and parsing those here.
+        self.stream.expect('block_end')
+        result = self.subparse(end_tokens)
+
+        # we reached the end of the template too early, the subparser
+        # does not check for this, so we do that now
+        if self.stream.current.type == 'eof':
+            self.fail_eof(end_tokens)
+
+        if drop_needle:
+            next(self.stream)
+        return result
+
+    def parse_set(self):
+        """Parse an assign statement."""
+        lineno = next(self.stream).lineno
+        target = self.parse_assign_target()
+        self.stream.expect('assign')
+        expr = self.parse_tuple()
+        return nodes.Assign(target, expr, lineno=lineno)
+
+    def parse_for(self):
+        """Parse a for loop."""
+        lineno = self.stream.expect('name:for').lineno
+        target = self.parse_assign_target(extra_end_rules=('name:in',))
+        self.stream.expect('name:in')
+        iter = self.parse_tuple(with_condexpr=False,
+                                extra_end_rules=('name:recursive',))
+        test = None
+        if self.stream.skip_if('name:if'):
+            test = self.parse_expression()
+        recursive = self.stream.skip_if('name:recursive')
+        body = self.parse_statements(('name:endfor', 'name:else'))
+        if next(self.stream).value == 'endfor':
+            else_ = []
+        else:
+            else_ = self.parse_statements(('name:endfor',), drop_needle=True)
+        return nodes.For(target, iter, body, else_, test,
+                         recursive, lineno=lineno)
+
+    def parse_if(self):
+        """Parse an if construct."""
+        node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
+        while 1:
+            node.test = self.parse_tuple(with_condexpr=False)
+            node.body = self.parse_statements(('name:elif', 'name:else',
+                                               'name:endif'))
+            token = next(self.stream)
+            if token.test('name:elif'):
+                new_node = nodes.If(lineno=self.stream.current.lineno)
+                node.else_ = [new_node]
+                node = new_node
+                continue
+            elif token.test('name:else'):
+                node.else_ = self.parse_statements(('name:endif',),
+                                                   drop_needle=True)
+            else:
+                node.else_ = []
+            break
+        return result
+
+    def parse_block(self):
+        node = nodes.Block(lineno=next(self.stream).lineno)
+        node.name = self.stream.expect('name').value
+        node.scoped = self.stream.skip_if('name:scoped')
+
+        # common problem people encounter when switching from django
+        # to jinja.  we do not support hyphens in block names, so let's
+        # raise a nicer error message in that case.
+        if self.stream.current.type == 'sub':
+            self.fail('Block names in Jinja have to be valid Python '
+                      'identifiers and may not contain hypens, use an '
+                      'underscore instead.')
+
+        node.body = self.parse_statements(('name:endblock',), drop_needle=True)
+        self.stream.skip_if('name:' + node.name)
+        return node
+
+    def parse_extends(self):
+        node = nodes.Extends(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        return node
+
+    def parse_import_context(self, node, default):
+        if self.stream.current.test_any('name:with', 'name:without') and \
+           self.stream.look().test('name:context'):
+            node.with_context = next(self.stream).value == 'with'
+            self.stream.skip()
+        else:
+            node.with_context = default
+        return node
+
+    def parse_include(self):
+        node = nodes.Include(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        if self.stream.current.test('name:ignore') and \
+           self.stream.look().test('name:missing'):
+            node.ignore_missing = True
+            self.stream.skip(2)
+        else:
+            node.ignore_missing = False
+        return self.parse_import_context(node, True)
+
+    def parse_import(self):
+        node = nodes.Import(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        self.stream.expect('name:as')
+        node.target = self.parse_assign_target(name_only=True).name
+        return self.parse_import_context(node, False)
+
+    def parse_from(self):
+        node = nodes.FromImport(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        self.stream.expect('name:import')
+        node.names = []
+
+        def parse_context():
+            if self.stream.current.value in ('with', 'without') and \
+               self.stream.look().test('name:context'):
+                node.with_context = next(self.stream).value == 'with'
+                self.stream.skip()
+                return True
+            return False
+
+        while 1:
+            if node.names:
+                self.stream.expect('comma')
+            if self.stream.current.type == 'name':
+                if parse_context():
+                    break
+                target = self.parse_assign_target(name_only=True)
+                if target.name.startswith('_'):
+                    self.fail('names starting with an underline can not '
+                              'be imported', target.lineno,
+                              exc=TemplateAssertionError)
+                if self.stream.skip_if('name:as'):
+                    alias = self.parse_assign_target(name_only=True)
+                    node.names.append((target.name, alias.name))
+                else:
+                    node.names.append(target.name)
+                if parse_context() or self.stream.current.type != 'comma':
+                    break
+            else:
+                break
+        if not hasattr(node, 'with_context'):
+            node.with_context = False
+            self.stream.skip_if('comma')
+        return node
+
+    def parse_signature(self, node):
+        node.args = args = []
+        node.defaults = defaults = []
+        self.stream.expect('lparen')
+        while self.stream.current.type != 'rparen':
+            if args:
+                self.stream.expect('comma')
+            arg = self.parse_assign_target(name_only=True)
+            arg.set_ctx('param')
+            if self.stream.skip_if('assign'):
+                defaults.append(self.parse_expression())
+            args.append(arg)
+        self.stream.expect('rparen')
+
+    def parse_call_block(self):
+        node = nodes.CallBlock(lineno=next(self.stream).lineno)
+        if self.stream.current.type == 'lparen':
+            self.parse_signature(node)
+        else:
+            node.args = []
+            node.defaults = []
+
+        node.call = self.parse_expression()
+        if not isinstance(node.call, nodes.Call):
+            self.fail('expected call', node.lineno)
+        node.body = self.parse_statements(('name:endcall',), drop_needle=True)
+        return node
+
+    def parse_filter_block(self):
+        node = nodes.FilterBlock(lineno=next(self.stream).lineno)
+        node.filter = self.parse_filter(None, start_inline=True)
+        node.body = self.parse_statements(('name:endfilter',),
+                                          drop_needle=True)
+        return node
+
+    def parse_macro(self):
+        node = nodes.Macro(lineno=next(self.stream).lineno)
+        node.name = self.parse_assign_target(name_only=True).name
+        self.parse_signature(node)
+        node.body = self.parse_statements(('name:endmacro',),
+                                          drop_needle=True)
+        return node
+
+    def parse_print(self):
+        node = nodes.Output(lineno=next(self.stream).lineno)
+        node.nodes = []
+        while self.stream.current.type != 'block_end':
+            if node.nodes:
+                self.stream.expect('comma')
+            node.nodes.append(self.parse_expression())
+        return node
+
+    def parse_assign_target(self, with_tuple=True, name_only=False,
+                            extra_end_rules=None):
+        """Parse an assignment target.  As Jinja2 allows assignments to
+        tuples, this function can parse all allowed assignment targets.  Per
+        default assignments to tuples are parsed, that can be disable however
+        by setting `with_tuple` to `False`.  If only assignments to names are
+        wanted `name_only` can be set to `True`.  The `extra_end_rules`
+        parameter is forwarded to the tuple parsing function.
+        """
+        if name_only:
+            token = self.stream.expect('name')
+            target = nodes.Name(token.value, 'store', lineno=token.lineno)
+        else:
+            if with_tuple:
+                target = self.parse_tuple(simplified=True,
+                                          extra_end_rules=extra_end_rules)
+            else:
+                target = self.parse_primary()
+            target.set_ctx('store')
+        if not target.can_assign():
+            self.fail('can\'t assign to %r' % target.__class__.
+                      __name__.lower(), target.lineno)
+        return target
+
+    def parse_expression(self, with_condexpr=True):
+        """Parse an expression.  Per default all expressions are parsed, if
+        the optional `with_condexpr` parameter is set to `False` conditional
+        expressions are not parsed.
+        """
+        if with_condexpr:
+            return self.parse_condexpr()
+        return self.parse_or()
+
+    def parse_condexpr(self):
+        lineno = self.stream.current.lineno
+        expr1 = self.parse_or()
+        while self.stream.skip_if('name:if'):
+            expr2 = self.parse_or()
+            if self.stream.skip_if('name:else'):
+                expr3 = self.parse_condexpr()
+            else:
+                expr3 = None
+            expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return expr1
+
+    def parse_or(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_and()
+        while self.stream.skip_if('name:or'):
+            right = self.parse_and()
+            left = nodes.Or(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_and(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_not()
+        while self.stream.skip_if('name:and'):
+            right = self.parse_not()
+            left = nodes.And(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_not(self):
+        if self.stream.current.test('name:not'):
+            lineno = next(self.stream).lineno
+            return nodes.Not(self.parse_not(), lineno=lineno)
+        return self.parse_compare()
+
+    def parse_compare(self):
+        lineno = self.stream.current.lineno
+        expr = self.parse_add()
+        ops = []
+        while 1:
+            token_type = self.stream.current.type
+            if token_type in _compare_operators:
+                next(self.stream)
+                ops.append(nodes.Operand(token_type, self.parse_add()))
+            elif self.stream.skip_if('name:in'):
+                ops.append(nodes.Operand('in', self.parse_add()))
+            elif self.stream.current.test('name:not') and \
+                 self.stream.look().test('name:in'):
+                self.stream.skip(2)
+                ops.append(nodes.Operand('notin', self.parse_add()))
+            else:
+                break
+            lineno = self.stream.current.lineno
+        if not ops:
+            return expr
+        return nodes.Compare(expr, ops, lineno=lineno)
+
+    def parse_add(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_sub()
+        while self.stream.current.type == 'add':
+            next(self.stream)
+            right = self.parse_sub()
+            left = nodes.Add(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_sub(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_concat()
+        while self.stream.current.type == 'sub':
+            next(self.stream)
+            right = self.parse_concat()
+            left = nodes.Sub(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_concat(self):
+        lineno = self.stream.current.lineno
+        args = [self.parse_mul()]
+        while self.stream.current.type == 'tilde':
+            next(self.stream)
+            args.append(self.parse_mul())
+        if len(args) == 1:
+            return args[0]
+        return nodes.Concat(args, lineno=lineno)
+
+    def parse_mul(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_div()
+        while self.stream.current.type == 'mul':
+            next(self.stream)
+            right = self.parse_div()
+            left = nodes.Mul(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_div(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_floordiv()
+        while self.stream.current.type == 'div':
+            next(self.stream)
+            right = self.parse_floordiv()
+            left = nodes.Div(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_floordiv(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_mod()
+        while self.stream.current.type == 'floordiv':
+            next(self.stream)
+            right = self.parse_mod()
+            left = nodes.FloorDiv(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_mod(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_pow()
+        while self.stream.current.type == 'mod':
+            next(self.stream)
+            right = self.parse_pow()
+            left = nodes.Mod(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_pow(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_unary()
+        while self.stream.current.type == 'pow':
+            next(self.stream)
+            right = self.parse_unary()
+            left = nodes.Pow(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_unary(self, with_filter=True):
+        token_type = self.stream.current.type
+        lineno = self.stream.current.lineno
+        if token_type == 'sub':
+            next(self.stream)
+            node = nodes.Neg(self.parse_unary(False), lineno=lineno)
+        elif token_type == 'add':
+            next(self.stream)
+            node = nodes.Pos(self.parse_unary(False), lineno=lineno)
+        else:
+            node = self.parse_primary()
+        node = self.parse_postfix(node)
+        if with_filter:
+            node = self.parse_filter_expr(node)
+        return node
+
+    def parse_primary(self):
+        token = self.stream.current
+        if token.type == 'name':
+            if token.value in ('true', 'false', 'True', 'False'):
+                node = nodes.Const(token.value in ('true', 'True'),
+                                   lineno=token.lineno)
+            elif token.value in ('none', 'None'):
+                node = nodes.Const(None, lineno=token.lineno)
+            else:
+                node = nodes.Name(token.value, 'load', lineno=token.lineno)
+            next(self.stream)
+        elif token.type == 'string':
+            next(self.stream)
+            buf = [token.value]
+            lineno = token.lineno
+            while self.stream.current.type == 'string':
+                buf.append(self.stream.current.value)
+                next(self.stream)
+            node = nodes.Const(''.join(buf), lineno=lineno)
+        elif token.type in ('integer', 'float'):
+            next(self.stream)
+            node = nodes.Const(token.value, lineno=token.lineno)
+        elif token.type == 'lparen':
+            next(self.stream)
+            node = self.parse_tuple(explicit_parentheses=True)
+            self.stream.expect('rparen')
+        elif token.type == 'lbracket':
+            node = self.parse_list()
+        elif token.type == 'lbrace':
+            node = self.parse_dict()
+        else:
+            self.fail("unexpected '%s'" % describe_token(token), token.lineno)
+        return node
+
+    def parse_tuple(self, simplified=False, with_condexpr=True,
+                    extra_end_rules=None, explicit_parentheses=False):
+        """Works like `parse_expression` but if multiple expressions are
+        delimited by a comma a :class:`~ambari_jinja2.nodes.Tuple` node is created.
+        This method could also return a regular expression instead of a tuple
+        if no commas where found.
+
+        The default parsing mode is a full tuple.  If `simplified` is `True`
+        only names and literals are parsed.  The `no_condexpr` parameter is
+        forwarded to :meth:`parse_expression`.
+
+        Because tuples do not require delimiters and may end in a bogus comma
+        an extra hint is needed that marks the end of a tuple.  For example
+        for loops support tuples between `for` and `in`.  In that case the
+        `extra_end_rules` is set to ``['name:in']``.
+
+        `explicit_parentheses` is true if the parsing was triggered by an
+        expression in parentheses.  This is used to figure out if an empty
+        tuple is a valid expression or not.
+        """
+        lineno = self.stream.current.lineno
+        if simplified:
+            parse = self.parse_primary
+        elif with_condexpr:
+            parse = self.parse_expression
+        else:
+            parse = lambda: self.parse_expression(with_condexpr=False)
+        args = []
+        is_tuple = False
+        while 1:
+            if args:
+                self.stream.expect('comma')
+            if self.is_tuple_end(extra_end_rules):
+                break
+            args.append(parse())
+            if self.stream.current.type == 'comma':
+                is_tuple = True
+            else:
+                break
+            lineno = self.stream.current.lineno
+
+        if not is_tuple:
+            if args:
+                return args[0]
+
+            # if we don't have explicit parentheses, an empty tuple is
+            # not a valid expression.  This would mean nothing (literally
+            # nothing) in the spot of an expression would be an empty
+            # tuple.
+            if not explicit_parentheses:
+                self.fail('Expected an expression, got \'%s\'' %
+                          describe_token(self.stream.current))
+
+        return nodes.Tuple(args, 'load', lineno=lineno)
+
+    def parse_list(self):
+        token = self.stream.expect('lbracket')
+        items = []
+        while self.stream.current.type != 'rbracket':
+            if items:
+                self.stream.expect('comma')
+            if self.stream.current.type == 'rbracket':
+                break
+            items.append(self.parse_expression())
+        self.stream.expect('rbracket')
+        return nodes.List(items, lineno=token.lineno)
+
+    def parse_dict(self):
+        token = self.stream.expect('lbrace')
+        items = []
+        while self.stream.current.type != 'rbrace':
+            if items:
+                self.stream.expect('comma')
+            if self.stream.current.type == 'rbrace':
+                break
+            key = self.parse_expression()
+            self.stream.expect('colon')
+            value = self.parse_expression()
+            items.append(nodes.Pair(key, value, lineno=key.lineno))
+        self.stream.expect('rbrace')
+        return nodes.Dict(items, lineno=token.lineno)
+
+    def parse_postfix(self, node):
+        while 1:
+            token_type = self.stream.current.type
+            if token_type == 'dot' or token_type == 'lbracket':
+                node = self.parse_subscript(node)
+            # calls are valid both after postfix expressions (getattr
+            # and getitem) as well as filters and tests
+            elif token_type == 'lparen':
+                node = self.parse_call(node)
+            else:
+                break
+        return node
+
+    def parse_filter_expr(self, node):
+        while 1:
+            token_type = self.stream.current.type
+            if token_type == 'pipe':
+                node = self.parse_filter(node)
+            elif token_type == 'name' and self.stream.current.value == 'is':
+                node = self.parse_test(node)
+            # calls are valid both after postfix expressions (getattr
+            # and getitem) as well as filters and tests
+            elif token_type == 'lparen':
+                node = self.parse_call(node)
+            else:
+                break
+        return node
+
+    def parse_subscript(self, node):
+        token = next(self.stream)
+        if token.type == 'dot':
+            attr_token = self.stream.current
+            next(self.stream)
+            if attr_token.type == 'name':
+                return nodes.Getattr(node, attr_token.value, 'load',
+                                     lineno=token.lineno)
+            elif attr_token.type != 'integer':
+                self.fail('expected name or number', attr_token.lineno)
+            arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
+            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
+        if token.type == 'lbracket':
+            priority_on_attribute = False
+            args = []
+            while self.stream.current.type != 'rbracket':
+                if args:
+                    self.stream.expect('comma')
+                args.append(self.parse_subscribed())
+            self.stream.expect('rbracket')
+            if len(args) == 1:
+                arg = args[0]
+            else:
+                arg = nodes.Tuple(args, 'load', lineno=token.lineno)
+            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
+        self.fail('expected subscript expression', self.lineno)
+
+    def parse_subscribed(self):
+        lineno = self.stream.current.lineno
+
+        if self.stream.current.type == 'colon':
+            next(self.stream)
+            args = [None]
+        else:
+            node = self.parse_expression()
+            if self.stream.current.type != 'colon':
+                return node
+            next(self.stream)
+            args = [node]
+
+        if self.stream.current.type == 'colon':
+            args.append(None)
+        elif self.stream.current.type not in ('rbracket', 'comma'):
+            args.append(self.parse_expression())
+        else:
+            args.append(None)
+
+        if self.stream.current.type == 'colon':
+            next(self.stream)
+            if self.stream.current.type not in ('rbracket', 'comma'):
+                args.append(self.parse_expression())
+            else:
+                args.append(None)
+        else:
+            args.append(None)
+
+        return nodes.Slice(lineno=lineno, *args)
+
+    def parse_call(self, node):
+        token = self.stream.expect('lparen')
+        args = []
+        kwargs = []
+        dyn_args = dyn_kwargs = None
+        require_comma = False
+
+        def ensure(expr):
+            if not expr:
+                self.fail('invalid syntax for function call expression',
+                          token.lineno)
+
+        while self.stream.current.type != 'rparen':
+            if require_comma:
+                self.stream.expect('comma')
+                # support for trailing comma
+                if self.stream.current.type == 'rparen':
+                    break
+            if self.stream.current.type == 'mul':
+                ensure(dyn_args is None and dyn_kwargs is None)
+                next(self.stream)
+                dyn_args = self.parse_expression()
+            elif self.stream.current.type == 'pow':
+                ensure(dyn_kwargs is None)
+                next(self.stream)
+                dyn_kwargs = self.parse_expression()
+            else:
+                ensure(dyn_args is None and dyn_kwargs is None)
+                if self.stream.current.type == 'name' and \
+                    self.stream.look().type == 'assign':
+                    key = self.stream.current.value
+                    self.stream.skip(2)
+                    value = self.parse_expression()
+                    kwargs.append(nodes.Keyword(key, value,
+                                                lineno=value.lineno))
+                else:
+                    ensure(not kwargs)
+                    args.append(self.parse_expression())
+
+            require_comma = True
+        self.stream.expect('rparen')
+
+        if node is None:
+            return args, kwargs, dyn_args, dyn_kwargs
+        return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
+                          lineno=token.lineno)
+
+    def parse_filter(self, node, start_inline=False):
+        while self.stream.current.type == 'pipe' or start_inline:
+            if not start_inline:
+                next(self.stream)
+            token = self.stream.expect('name')
+            name = token.value
+            while self.stream.current.type == 'dot':
+                next(self.stream)
+                name += '.' + self.stream.expect('name').value
+            if self.stream.current.type == 'lparen':
+                args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
+            else:
+                args = []
+                kwargs = []
+                dyn_args = dyn_kwargs = None
+            node = nodes.Filter(node, name, args, kwargs, dyn_args,
+                                dyn_kwargs, lineno=token.lineno)
+            start_inline = False
+        return node
+
+    def parse_test(self, node):
+        token = next(self.stream)
+        if self.stream.current.test('name:not'):
+            next(self.stream)
+            negated = True
+        else:
+            negated = False
+        name = self.stream.expect('name').value
+        while self.stream.current.type == 'dot':
+            next(self.stream)
+            name += '.' + self.stream.expect('name').value
+        dyn_args = dyn_kwargs = None
+        kwargs = []
+        if self.stream.current.type == 'lparen':
+            args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
+        elif self.stream.current.type in ('name', 'string', 'integer',
+                                          'float', 'lparen', 'lbracket',
+                                          'lbrace') and not \
+             self.stream.current.test_any('name:else', 'name:or',
+                                          'name:and'):
+            if self.stream.current.test('name:is'):
+                self.fail('You cannot chain multiple tests with is')
+            args = [self.parse_expression()]
+        else:
+            args = []
+        node = nodes.Test(node, name, args, kwargs, dyn_args,
+                          dyn_kwargs, lineno=token.lineno)
+        if negated:
+            node = nodes.Not(node, lineno=token.lineno)
+        return node
+
+    def subparse(self, end_tokens=None):
+        body = []
+        data_buffer = []
+        add_data = data_buffer.append
+
+        if end_tokens is not None:
+            self._end_token_stack.append(end_tokens)
+
+        def flush_data():
+            if data_buffer:
+                lineno = data_buffer[0].lineno
+                body.append(nodes.Output(data_buffer[:], lineno=lineno))
+                del data_buffer[:]
+
+        try:
+            while self.stream:
+                token = self.stream.current
+                if token.type == 'data':
+                    if token.value:
+                        add_data(nodes.TemplateData(token.value,
+                                                    lineno=token.lineno))
+                    next(self.stream)
+                elif token.type == 'variable_begin':
+                    next(self.stream)
+                    add_data(self.parse_tuple(with_condexpr=True))
+                    self.stream.expect('variable_end')
+                elif token.type == 'block_begin':
+                    flush_data()
+                    next(self.stream)
+                    if end_tokens is not None and \
+                       self.stream.current.test_any(*end_tokens):
+                        return body
+                    rv = self.parse_statement()
+                    if isinstance(rv, list):
+                        body.extend(rv)
+                    else:
+                        body.append(rv)
+                    self.stream.expect('block_end')
+                else:
+                    raise AssertionError('internal parsing error')
+
+            flush_data()
+        finally:
+            if end_tokens is not None:
+                self._end_token_stack.pop()
+
+        return body
+
+    def parse(self):
+        """Parse the whole template into a `Template` node."""
+        result = nodes.Template(self.subparse(), lineno=1)
+        result.set_environment(self.environment)
+        return result

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py
new file mode 100644
index 0000000..0830132
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/runtime.py
@@ -0,0 +1,544 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.runtime
+    ~~~~~~~~~~~~~~
+
+    Runtime helpers.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+import sys
+from itertools import chain, imap
+from ambari_jinja2.nodes import EvalContext, _context_function_types
+from ambari_jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
+     concat, internalcode, next, object_type_repr
+from ambari_jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
+     TemplateNotFound
+
+
+# these variables are exported to the template runtime
+__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
+           'TemplateRuntimeError', 'missing', 'concat', 'escape',
+           'markup_join', 'unicode_join', 'to_string', 'identity',
+           'TemplateNotFound']
+
+#: the name of the function that is used to convert something into
+#: a string.  2to3 will adopt that automatically and the generated
+#: code can take advantage of it.
+to_string = unicode
+
+#: the identity function.  Useful for certain things in the environment
+identity = lambda x: x
+
+
+def markup_join(seq):
+    """Concatenation that escapes if necessary and converts to unicode."""
+    buf = []
+    iterator = imap(soft_unicode, seq)
+    for arg in iterator:
+        buf.append(arg)
+        if hasattr(arg, '__html__'):
+            return Markup(u'').join(chain(buf, iterator))
+    return concat(buf)
+
+
+def unicode_join(seq):
+    """Simple args to unicode conversion and concatenation."""
+    return concat(imap(unicode, seq))
+
+
+def new_context(environment, template_name, blocks, vars=None,
+                shared=None, globals=None, locals=None):
+    """Internal helper to for context creation."""
+    if vars is None:
+        vars = {}
+    if shared:
+        parent = vars
+    else:
+        parent = dict(globals or (), **vars)
+    if locals:
+        # if the parent is shared a copy should be created because
+        # we don't want to modify the dict passed
+        if shared:
+            parent = dict(parent)
+        for key, value in locals.iteritems():
+            if key[:2] == 'l_' and value is not missing:
+                parent[key[2:]] = value
+    return Context(environment, parent, template_name, blocks)
+
+
+class TemplateReference(object):
+    """The `self` in templates."""
+
+    def __init__(self, context):
+        self.__context = context
+
+    def __getitem__(self, name):
+        blocks = self.__context.blocks[name]
+        wrap = self.__context.eval_ctx.autoescape and \
+               Markup or (lambda x: x)
+        return BlockReference(name, self.__context, blocks, 0)
+
+    def __repr__(self):
+        return '<%s %r>' % (
+            self.__class__.__name__,
+            self.__context.name
+        )
+
+
+class Context(object):
+    """The template context holds the variables of a template.  It stores the
+    values passed to the template and also the names the template exports.
+    Creating instances is neither supported nor useful as it's created
+    automatically at various stages of the template evaluation and should not
+    be created by hand.
+
+    The context is immutable.  Modifications on :attr:`parent` **must not**
+    happen and modifications on :attr:`vars` are allowed from generated
+    template code only.  Template filters and global functions marked as
+    :func:`contextfunction`\s get the active context passed as first argument
+    and are allowed to access the context read-only.
+
+    The template context supports read only dict operations (`get`,
+    `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
+    `__getitem__`, `__contains__`).  Additionally there is a :meth:`resolve`
+    method that doesn't fail with a `KeyError` but returns an
+    :class:`Undefined` object for missing variables.
+    """
+    __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
+                 'name', 'blocks', '__weakref__')
+
+    def __init__(self, environment, parent, name, blocks):
+        self.parent = parent
+        self.vars = {}
+        self.environment = environment
+        self.eval_ctx = EvalContext(self.environment, name)
+        self.exported_vars = set()
+        self.name = name
+
+        # create the initial mapping of blocks.  Whenever template inheritance
+        # takes place the runtime will update this mapping with the new blocks
+        # from the template.
+        self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
+
+    def super(self, name, current):
+        """Render a parent block."""
+        try:
+            blocks = self.blocks[name]
+            index = blocks.index(current) + 1
+            blocks[index]
+        except LookupError:
+            return self.environment.undefined('there is no parent block '
+                                              'called %r.' % name,
+                                              name='super')
+        return BlockReference(name, self, blocks, index)
+
+    def get(self, key, default=None):
+        """Returns an item from the template context, if it doesn't exist
+        `default` is returned.
+        """
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def resolve(self, key):
+        """Looks up a variable like `__getitem__` or `get` but returns an
+        :class:`Undefined` object with the name of the name looked up.
+        """
+        if key in self.vars:
+            return self.vars[key]
+        if key in self.parent:
+            return self.parent[key]
+        return self.environment.undefined(name=key)
+
+    def get_exported(self):
+        """Get a new dict with the exported variables."""
+        return dict((k, self.vars[k]) for k in self.exported_vars)
+
+    def get_all(self):
+        """Return a copy of the complete context as dict including the
+        exported variables.
+        """
+        return dict(self.parent, **self.vars)
+
+    @internalcode
+    def call(__self, __obj, *args, **kwargs):
+        """Call the callable with the arguments and keyword arguments
+        provided but inject the active context or environment as first
+        argument if the callable is a :func:`contextfunction` or
+        :func:`environmentfunction`.
+        """
+        if __debug__:
+            __traceback_hide__ = True
+        if isinstance(__obj, _context_function_types):
+            if getattr(__obj, 'contextfunction', 0):
+                args = (__self,) + args
+            elif getattr(__obj, 'evalcontextfunction', 0):
+                args = (__self.eval_ctx,) + args
+            elif getattr(__obj, 'environmentfunction', 0):
+                args = (__self.environment,) + args
+        try:
+            return __obj(*args, **kwargs)
+        except StopIteration:
+            return __self.environment.undefined('value was undefined because '
+                                                'a callable raised a '
+                                                'StopIteration exception')
+
+    def derived(self, locals=None):
+        """Internal helper function to create a derived context."""
+        context = new_context(self.environment, self.name, {},
+                              self.parent, True, None, locals)
+        context.eval_ctx = self.eval_ctx
+        context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
+        return context
+
+    def _all(meth):
+        proxy = lambda self: getattr(self.get_all(), meth)()
+        proxy.__doc__ = getattr(dict, meth).__doc__
+        proxy.__name__ = meth
+        return proxy
+
+    keys = _all('keys')
+    values = _all('values')
+    items = _all('items')
+
+    # not available on python 3
+    if hasattr(dict, 'iterkeys'):
+        iterkeys = _all('iterkeys')
+        itervalues = _all('itervalues')
+        iteritems = _all('iteritems')
+    del _all
+
+    def __contains__(self, name):
+        return name in self.vars or name in self.parent
+
+    def __getitem__(self, key):
+        """Lookup a variable or raise `KeyError` if the variable is
+        undefined.
+        """
+        item = self.resolve(key)
+        if isinstance(item, Undefined):
+            raise KeyError(key)
+        return item
+
+    def __repr__(self):
+        return '<%s %s of %r>' % (
+            self.__class__.__name__,
+            repr(self.get_all()),
+            self.name
+        )
+
+
+# register the context as mapping if possible
+try:
+    from collections import Mapping
+    Mapping.register(Context)
+except ImportError:
+    pass
+
+
+class BlockReference(object):
+    """One block on a template reference."""
+
+    def __init__(self, name, context, stack, depth):
+        self.name = name
+        self._context = context
+        self._stack = stack
+        self._depth = depth
+
+    @property
+    def super(self):
+        """Super the block."""
+        if self._depth + 1 >= len(self._stack):
+            return self._context.environment. \
+                undefined('there is no parent block called %r.' %
+                          self.name, name='super')
+        return BlockReference(self.name, self._context, self._stack,
+                              self._depth + 1)
+
+    @internalcode
+    def __call__(self):
+        rv = concat(self._stack[self._depth](self._context))
+        if self._context.eval_ctx.autoescape:
+            rv = Markup(rv)
+        return rv
+
+
+class LoopContext(object):
+    """A loop context for dynamic iteration."""
+
+    def __init__(self, iterable, recurse=None):
+        self._iterator = iter(iterable)
+        self._recurse = recurse
+        self.index0 = -1
+
+        # try to get the length of the iterable early.  This must be done
+        # here because there are some broken iterators around where there
+        # __len__ is the number of iterations left (i'm looking at your
+        # listreverseiterator!).
+        try:
+            self._length = len(iterable)
+        except (TypeError, AttributeError):
+            self._length = None
+
+    def cycle(self, *args):
+        """Cycles among the arguments with the current loop index."""
+        if not args:
+            raise TypeError('no items for cycling given')
+        return args[self.index0 % len(args)]
+
+    first = property(lambda x: x.index0 == 0)
+    last = property(lambda x: x.index0 + 1 == x.length)
+    index = property(lambda x: x.index0 + 1)
+    revindex = property(lambda x: x.length - x.index0)
+    revindex0 = property(lambda x: x.length - x.index)
+
+    def __len__(self):
+        return self.length
+
+    def __iter__(self):
+        return LoopContextIterator(self)
+
+    @internalcode
+    def loop(self, iterable):
+        if self._recurse is None:
+            raise TypeError('Tried to call non recursive loop.  Maybe you '
+                            "forgot the 'recursive' modifier.")
+        return self._recurse(iterable, self._recurse)
+
+    # a nifty trick to enhance the error message if someone tried to call
+    # the the loop without or with too many arguments.
+    __call__ = loop
+    del loop
+
+    @property
+    def length(self):
+        if self._length is None:
+            # if was not possible to get the length of the iterator when
+            # the loop context was created (ie: iterating over a generator)
+            # we have to convert the iterable into a sequence and use the
+            # length of that.
+            iterable = tuple(self._iterator)
+            self._iterator = iter(iterable)
+            self._length = len(iterable) + self.index0 + 1
+        return self._length
+
+    def __repr__(self):
+        return '<%s %r/%r>' % (
+            self.__class__.__name__,
+            self.index,
+            self.length
+        )
+
+
+class LoopContextIterator(object):
+    """The iterator for a loop context."""
+    __slots__ = ('context',)
+
+    def __init__(self, context):
+        self.context = context
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        ctx = self.context
+        ctx.index0 += 1
+        return next(ctx._iterator), ctx
+
+
+class Macro(object):
+    """Wraps a macro function."""
+
+    def __init__(self, environment, func, name, arguments, defaults,
+                 catch_kwargs, catch_varargs, caller):
+        self._environment = environment
+        self._func = func
+        self._argument_count = len(arguments)
+        self.name = name
+        self.arguments = arguments
+        self.defaults = defaults
+        self.catch_kwargs = catch_kwargs
+        self.catch_varargs = catch_varargs
+        self.caller = caller
+
+    @internalcode
+    def __call__(self, *args, **kwargs):
+        # try to consume the positional arguments
+        arguments = list(args[:self._argument_count])
+        off = len(arguments)
+
+        # if the number of arguments consumed is not the number of
+        # arguments expected we start filling in keyword arguments
+        # and defaults.
+        if off != self._argument_count:
+            for idx, name in enumerate(self.arguments[len(arguments):]):
+                try:
+                    value = kwargs.pop(name)
+                except KeyError:
+                    try:
+                        value = self.defaults[idx - self._argument_count + off]
+                    except IndexError:
+                        value = self._environment.undefined(
+                            'parameter %r was not provided' % name, name=name)
+                arguments.append(value)
+
+        # it's important that the order of these arguments does not change
+        # if not also changed in the compiler's `function_scoping` method.
+        # the order is caller, keyword arguments, positional arguments!
+        if self.caller:
+            caller = kwargs.pop('caller', None)
+            if caller is None:
+                caller = self._environment.undefined('No caller defined',
+                                                     name='caller')
+            arguments.append(caller)
+        if self.catch_kwargs:
+            arguments.append(kwargs)
+        elif kwargs:
+            raise TypeError('macro %r takes no keyword argument %r' %
+                            (self.name, next(iter(kwargs))))
+        if self.catch_varargs:
+            arguments.append(args[self._argument_count:])
+        elif len(args) > self._argument_count:
+            raise TypeError('macro %r takes not more than %d argument(s)' %
+                            (self.name, len(self.arguments)))
+        return self._func(*arguments)
+
+    def __repr__(self):
+        return '<%s %s>' % (
+            self.__class__.__name__,
+            self.name is None and 'anonymous' or repr(self.name)
+        )
+
+
+class Undefined(object):
+    """The default undefined type.  This undefined type can be printed and
+    iterated over, but every other access will raise an :exc:`UndefinedError`:
+
+    >>> foo = Undefined(name='foo')
+    >>> str(foo)
+    ''
+    >>> not foo
+    True
+    >>> foo + 42
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    """
+    __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
+                 '_undefined_exception')
+
+    def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
+        self._undefined_hint = hint
+        self._undefined_obj = obj
+        self._undefined_name = name
+        self._undefined_exception = exc
+
+    @internalcode
+    def _fail_with_undefined_error(self, *args, **kwargs):
+        """Regular callback function for undefined objects that raises an
+        `UndefinedError` on call.
+        """
+        if self._undefined_hint is None:
+            if self._undefined_obj is missing:
+                hint = '%r is undefined' % self._undefined_name
+            elif not isinstance(self._undefined_name, basestring):
+                hint = '%s has no element %r' % (
+                    object_type_repr(self._undefined_obj),
+                    self._undefined_name
+                )
+            else:
+                hint = '%r has no attribute %r' % (
+                    object_type_repr(self._undefined_obj),
+                    self._undefined_name
+                )
+        else:
+            hint = self._undefined_hint
+        raise self._undefined_exception(hint)
+
+    __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
+    __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
+    __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
+    __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
+    __int__ = __float__ = __complex__ = __pow__ = __rpow__ = \
+        _fail_with_undefined_error
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        return u''
+
+    def __len__(self):
+        return 0
+
+    def __iter__(self):
+        if 0:
+            yield None
+
+    def __nonzero__(self):
+        return False
+
+    def __repr__(self):
+        return 'Undefined'
+
+
+class DebugUndefined(Undefined):
+    """An undefined that returns the debug info when printed.
+
+    >>> foo = DebugUndefined(name='foo')
+    >>> str(foo)
+    '{{ foo }}'
+    >>> not foo
+    True
+    >>> foo + 42
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    """
+    __slots__ = ()
+
+    def __unicode__(self):
+        if self._undefined_hint is None:
+            if self._undefined_obj is missing:
+                return u'{{ %s }}' % self._undefined_name
+            return '{{ no such element: %s[%r] }}' % (
+                object_type_repr(self._undefined_obj),
+                self._undefined_name
+            )
+        return u'{{ undefined value printed: %s }}' % self._undefined_hint
+
+
+class StrictUndefined(Undefined):
+    """An undefined that barks on print and iteration as well as boolean
+    tests and all kinds of comparisons.  In other words: you can do nothing
+    with it except checking if it's defined using the `defined` test.
+
+    >>> foo = StrictUndefined(name='foo')
+    >>> str(foo)
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    >>> not foo
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    >>> foo + 42
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    """
+    __slots__ = ()
+    __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
+        __ne__ = __bool__ = Undefined._fail_with_undefined_error
+
+
+# remove remaining slots attributes, after the metaclass did the magic they
+# are unneeded and irritating as they contain wrong data for the subclasses.
+del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__


[57/59] [abbrv] git commit: AMBARI-7153. Admin: error printed to log when going to admin view.

Posted by nc...@apache.org.
AMBARI-7153. Admin: error printed to log when going to admin view.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1946654b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1946654b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1946654b

Branch: refs/heads/branch-alerts-dev
Commit: 1946654b71da61d097b3fc139dc2d12e20a116cb
Parents: fcd8d1f
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Thu Sep 4 13:40:35 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Thu Sep 4 13:40:35 2014 -0700

----------------------------------------------------------------------
 .../server/configuration/Configuration.java     |  6 ++++++
 .../authorization/AmbariLdapDataPopulator.java  |  5 ++++-
 ambari-server/src/main/python/ambari-server.py  |  2 ++
 .../AmbariLdapDataPopulatorTest.java            | 22 +++++++++++---------
 .../src/test/python/TestAmbariServer.py         |  9 +++++---
 5 files changed, 30 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1946654b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 0d02b21..dc3a715 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -118,6 +118,7 @@ public class Configuration {
   public static final String OJDBC_JAR_NAME_DEFAULT = "ojdbc6.jar";
   public static final String MYSQL_JAR_NAME_KEY = "db.mysql.jdbc.name";
   public static final String MYSQL_JAR_NAME_DEFAULT = "mysql-connector-java.jar";
+  public static final String IS_LDAP_CONFIGURED = "ambari.ldap.isConfigured";
   public static final String LDAP_USE_SSL_KEY = "authentication.ldap.useSSL";
   public static final String LDAP_PRIMARY_URL_KEY =
       "authentication.ldap.primaryUrl";
@@ -280,6 +281,7 @@ public class Configuration {
   private static final String LDAP_ADMIN_GROUP_MAPPING_RULES_DEFAULT =
       "Ambari Administrators";
   private static final String LDAP_GROUP_SEARCH_FILTER_DEFAULT = "";
+  private static final String IS_LDAP_CONFIGURED_DEFAULT = "false";
   //TODO for development purposes only, should be changed to 'false'
   private static final String SERVER_PERSISTENCE_TYPE_DEFAULT = "local";
   private static final String SERVER_CONNECTION_MAX_IDLE_TIME =
@@ -804,6 +806,10 @@ public class Configuration {
     return ldapServerProperties;
   }
 
+  public boolean isLdapConfigured() {
+    return Boolean.parseBoolean(properties.getProperty(IS_LDAP_CONFIGURED, IS_LDAP_CONFIGURED_DEFAULT));
+  }
+
   public String getServerOsType() {
     return properties.getProperty(OS_VERSION_KEY, "");
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1946654b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulator.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulator.java
index b5f9341..a160716 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulator.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulator.java
@@ -84,12 +84,15 @@ public class AmbariLdapDataPopulator {
    * @return true if enabled
    */
   public boolean isLdapEnabled() {
+    if (!configuration.isLdapConfigured()) {
+      return false;
+    }
     try {
       final LdapTemplate ldapTemplate = loadLdapTemplate();
       ldapTemplate.list(ldapServerProperties.getBaseDN());
       return true;
     } catch (Exception ex) {
-      LOG.error("Could not connect to LDAP server", ex);
+      LOG.error("Could not connect to LDAP server - " + ex.getMessage());
       return false;
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1946654b/ambari-server/src/main/python/ambari-server.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari-server.py b/ambari-server/src/main/python/ambari-server.py
index 661c937..81b79d1 100755
--- a/ambari-server/src/main/python/ambari-server.py
+++ b/ambari-server/src/main/python/ambari-server.py
@@ -215,6 +215,7 @@ NAGIOS_HTTPS = 'nagios.https'
 JDBC_RCA_PASSWORD_ALIAS = "ambari.db.password"
 CLIENT_SECURITY_KEY = "client.security"
 
+IS_LDAP_CONFIGURED = "ambari.ldap.isConfigured"
 LDAP_MGR_PASSWORD_ALIAS = "ambari.ldap.manager.password"
 LDAP_MGR_PASSWORD_PROPERTY = "authentication.ldap.managerPassword"
 LDAP_MGR_USERNAME_PROPERTY = "authentication.ldap.managerDn"
@@ -3064,6 +3065,7 @@ def setup_ldap():
     pass
 
     # Persisting values
+    ldap_property_value_map[IS_LDAP_CONFIGURED] = "true"
     update_properties(properties, ldap_property_value_map)
     print 'Saving...done'
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1946654b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulatorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulatorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulatorTest.java
index 868df06..23f53cf 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulatorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLdapDataPopulatorTest.java
@@ -123,17 +123,18 @@ public class AmbariLdapDataPopulatorTest {
   }
 
   @Test
-  public void testIsLdapEnabled() {
+  public void testIsLdapEnabled_badConfiguration() {
     final Configuration configuration = EasyMock.createNiceMock(Configuration.class);
     final Users users = EasyMock.createNiceMock(Users.class);
 
     final AmbariLdapDataPopulator populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
 
-    EasyMock.expect(populator.loadLdapTemplate().list(EasyMock. <String>anyObject())).andReturn(Collections.emptyList()).once();
-    EasyMock.replay(populator.loadLdapTemplate());
+    EasyMock.expect(configuration.isLdapConfigured()).andReturn(true);
+    EasyMock.expect(populator.loadLdapTemplate().list(EasyMock. <String>anyObject())).andThrow(new NullPointerException()).once();
+    EasyMock.replay(populator.loadLdapTemplate(), configuration);
 
-    populator.isLdapEnabled();
-    EasyMock.verify(populator.loadLdapTemplate());
+    Assert.assertFalse(populator.isLdapEnabled());
+    EasyMock.verify(populator.loadLdapTemplate(), configuration);
   }
 
   @Test
@@ -143,11 +144,12 @@ public class AmbariLdapDataPopulatorTest {
 
     final AmbariLdapDataPopulator populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
 
+    EasyMock.expect(configuration.isLdapConfigured()).andReturn(true);
     EasyMock.expect(populator.loadLdapTemplate().list(EasyMock. <String>anyObject())).andReturn(Collections.emptyList()).once();
-    EasyMock.replay(populator.loadLdapTemplate());
+    EasyMock.replay(populator.loadLdapTemplate(),configuration);
 
     Assert.assertTrue(populator.isLdapEnabled());
-    EasyMock.verify(populator.loadLdapTemplate());
+    EasyMock.verify(populator.loadLdapTemplate(), configuration);
   }
 
   @Test
@@ -157,11 +159,11 @@ public class AmbariLdapDataPopulatorTest {
 
     final AmbariLdapDataPopulator populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
 
-    EasyMock.expect(populator.loadLdapTemplate().list(EasyMock. <String>anyObject())).andThrow(new NullPointerException()).once();
-    EasyMock.replay(populator.loadLdapTemplate());
+    EasyMock.expect(configuration.isLdapConfigured()).andReturn(false);
+    EasyMock.replay(populator.loadLdapTemplate(), configuration);
 
     Assert.assertFalse(populator.isLdapEnabled());
-    EasyMock.verify(populator.loadLdapTemplate());
+    EasyMock.verify(populator.loadLdapTemplate(), configuration);
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/1946654b/ambari-server/src/test/python/TestAmbariServer.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestAmbariServer.py b/ambari-server/src/test/python/TestAmbariServer.py
index 2ad6661..53f0ba1 100644
--- a/ambari-server/src/test/python/TestAmbariServer.py
+++ b/ambari-server/src/test/python/TestAmbariServer.py
@@ -4521,7 +4521,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
         "authentication.ldap.groupMembershipAttr": "member",
         "authentication.ldap.baseDn": "base",
         "authentication.ldap.bindAnonymously": "true",
-        "client.security": "ldap"
+        "client.security": "ldap",
+        "ambari.ldap.isConfigured": "true"
       }
 
     sorted_x = sorted(ldap_properties_map.iteritems(), key=operator.itemgetter(0))
@@ -4547,7 +4548,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
         "authentication.ldap.groupMembershipAttr": "member",
         "authentication.ldap.baseDn": "base",
         "authentication.ldap.bindAnonymously": "true",
-        "client.security": "ldap"
+        "client.security": "ldap",
+        "ambari.ldap.isConfigured": "true"
       }
 
     sorted_x = sorted(ldap_properties_map.iteritems(), key=operator.itemgetter(0))
@@ -4644,7 +4646,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
         "authentication.ldap.groupNamingAttr": "test",
         "client.security": "ldap", \
         ambari_server.LDAP_MGR_PASSWORD_PROPERTY: ambari_server.get_alias_string( \
-          ambari_server.LDAP_MGR_PASSWORD_ALIAS)
+          ambari_server.LDAP_MGR_PASSWORD_ALIAS),
+        "ambari.ldap.isConfigured": "true"
       }
 
     sorted_x = sorted(ldap_properties_map.iteritems(), key=operator.itemgetter(0))


[36/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py b/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py
deleted file mode 100644
index 1161b7f..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_stringdefs.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2._stringdefs
-    ~~~~~~~~~~~~~~~~~~
-
-    Strings of all Unicode characters of a certain category.
-    Used for matching in Unicode-aware languages. Run to regenerate.
-
-    Inspired by chartypes_create.py from the MoinMoin project, original
-    implementation from Pygments.
-
-    :copyright: Copyright 2006-2009 by the Jinja team, see AUTHORS.
-    :license: BSD, see LICENSE for details.
-"""
-
-Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
-
-Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb'
-
-Cn = u'\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0370\u0371\u0372\u0373\u0376\u0377\u0378\u0379\u037b\u037c\u037d\u037f\u0380\u0381\u0382\u0383\u038b\u038d\u03a2\u03cf\u0487\u04cf\u04fa\u04fb\u04fc\u04fd\u04fe\u04ff\u0510\u0511\u0512\u0513\u0514\u0515\u0516\u0517\u0518\u0519\u051a\u051b\u051c\u051d\u051e\u051f\u0520\u0521\u0522\u0523\u0524\u0525\u0526\u0527\u0528\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0557\u0558\u0560\u0588\u058b\u058c\u058d\u058e\u058f\u0590\u05ba\u05c8\u05c9\u05ca\u05cb\u05cc\u05cd\u05ce\u05cf\u05eb\u05ec\u05ed\u05ee\u05ef\u05f5\u05f6\u05f7\u05f8\u05f9\u05fa\u05fb\u05fc\u05fd\u05fe\u05ff\u0604\u0605\u0606\u0607\u0608\u0609\u060a\u0616\u0617\u0618\u0619\u061a\u061c\u061d\u0620\u063b\u063c\u063d\u063e\u063f\u065f\u070e\u074b\u074c\u076e\u076f\u0770\u0771\u0772\u0773\u0774\u0775\u0776\u0777\u0778\u0779\u077a\u077b\u077c\u077d\u077e\u077f\u07b2\u07b3\u07b4\u07b5\u07b6\u07b7\u07b8\u07b9\u07ba\u07bb\u07bc\u07bd\u07be
 \u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u07c7\u07c8\u07c9\u07ca\u07cb\u07cc\u07cd\u07ce\u07cf\u07d0\u07d1\u07d2\u07d3\u07d4\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07db\u07dc\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3\u07e4\u07e5\u07e6\u07e7\u07e8\u07e9\u07ea\u07eb\u07ec\u07ed\u07ee\u07ef\u07f0\u07f1\u07f2\u07f3\u07f4\u07f5\u07f6\u07f7\u07f8\u07f9\u07fa\u07fb\u07fc\u07fd\u07fe\u07ff\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u0817\u0818\u0819\u081a\u081b\u081c\u081d\u081e\u081f\u0820\u0821\u0822\u0823\u0824\u0825\u0826\u0827\u0828\u0829\u082a\u082b\u082c\u082d\u082e\u082f\u0830\u0831\u0832\u0833\u0834\u0835\u0836\u0837\u0838\u0839\u083a\u083b\u083c\u083d\u083e\u083f\u0840\u0841\u0842\u0843\u0844\u0845\u0846\u0847\u0848\u0849\u084a\u084b\u084c\u084d\u084e\u084f\u0850\u0851\u0852\u0853\u0854\u0855\u0856\u0857\u0858\u0859\u085a\u085b\u085c\u085d\u085e\u085f\u0860\u0861\u0862\u0863\u0864\
 u0865\u0866\u0867\u0868\u0869\u086a\u086b\u086c\u086d\u086e\u086f\u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087a\u087b\u087c\u087d\u087e\u087f\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0888\u0889\u088a\u088b\u088c\u088d\u088e\u088f\u0890\u0891\u0892\u0893\u0894\u0895\u0896\u0897\u0898\u0899\u089a\u089b\u089c\u089d\u089e\u089f\u08a0\u08a1\u08a2\u08a3\u08a4\u08a5\u08a6\u08a7\u08a8\u08a9\u08aa\u08ab\u08ac\u08ad\u08ae\u08af\u08b0\u08b1\u08b2\u08b3\u08b4\u08b5\u08b6\u08b7\u08b8\u08b9\u08ba\u08bb\u08bc\u08bd\u08be\u08bf\u08c0\u08c1\u08c2\u08c3\u08c4\u08c5\u08c6\u08c7\u08c8\u08c9\u08ca\u08cb\u08cc\u08cd\u08ce\u08cf\u08d0\u08d1\u08d2\u08d3\u08d4\u08d5\u08d6\u08d7\u08d8\u08d9\u08da\u08db\u08dc\u08dd\u08de\u08df\u08e0\u08e1\u08e2\u08e3\u08e4\u08e5\u08e6\u08e7\u08e8\u08e9\u08ea\u08eb\u08ec\u08ed\u08ee\u08ef\u08f0\u08f1\u08f2\u08f3\u08f4\u08f5\u08f6\u08f7\u08f8\u08f9\u08fa\u08fb\u08fc\u08fd\u08fe\u08ff\u0900\u093a\u093b\u094e\u094f\u0955\u0956\u0957\u0971\u0972\u0973\u
 0974\u0975\u0976\u0977\u0978\u0979\u097a\u097b\u097c\u097e\u097f\u0980\u0984\u098d\u098e\u0991\u0992\u09a9\u09b1\u09b3\u09b4\u09b5\u09ba\u09bb\u09c5\u09c6\u09c9\u09ca\u09cf\u09d0\u09d1\u09d2\u09d3\u09d4\u09d5\u09d6\u09d8\u09d9\u09da\u09db\u09de\u09e4\u09e5\u09fb\u09fc\u09fd\u09fe\u09ff\u0a00\u0a04\u0a0b\u0a0c\u0a0d\u0a0e\u0a11\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a\u0a3b\u0a3d\u0a43\u0a44\u0a45\u0a46\u0a49\u0a4a\u0a4e\u0a4f\u0a50\u0a51\u0a52\u0a53\u0a54\u0a55\u0a56\u0a57\u0a58\u0a5d\u0a5f\u0a60\u0a61\u0a62\u0a63\u0a64\u0a65\u0a75\u0a76\u0a77\u0a78\u0a79\u0a7a\u0a7b\u0a7c\u0a7d\u0a7e\u0a7f\u0a80\u0a84\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba\u0abb\u0ac6\u0aca\u0ace\u0acf\u0ad1\u0ad2\u0ad3\u0ad4\u0ad5\u0ad6\u0ad7\u0ad8\u0ad9\u0ada\u0adb\u0adc\u0add\u0ade\u0adf\u0ae4\u0ae5\u0af0\u0af2\u0af3\u0af4\u0af5\u0af6\u0af7\u0af8\u0af9\u0afa\u0afb\u0afc\u0afd\u0afe\u0aff\u0b00\u0b04\u0b0d\u0b0e\u0b11\u0b12\u0b29\u0b31\u0b34\u0b3a\u0b3b\u0b44\u0b45\u0b46\u0b49\u0b4a\u0b4e\u0b4f\u0b50\u0b51\u0b52\u0b53\u0
 b54\u0b55\u0b58\u0b59\u0b5a\u0b5b\u0b5e\u0b62\u0b63\u0b64\u0b65\u0b72\u0b73\u0b74\u0b75\u0b76\u0b77\u0b78\u0b79\u0b7a\u0b7b\u0b7c\u0b7d\u0b7e\u0b7f\u0b80\u0b81\u0b84\u0b8b\u0b8c\u0b8d\u0b91\u0b96\u0b97\u0b98\u0b9b\u0b9d\u0ba0\u0ba1\u0ba2\u0ba5\u0ba6\u0ba7\u0bab\u0bac\u0bad\u0bba\u0bbb\u0bbc\u0bbd\u0bc3\u0bc4\u0bc5\u0bc9\u0bce\u0bcf\u0bd0\u0bd1\u0bd2\u0bd3\u0bd4\u0bd5\u0bd6\u0bd8\u0bd9\u0bda\u0bdb\u0bdc\u0bdd\u0bde\u0bdf\u0be0\u0be1\u0be2\u0be3\u0be4\u0be5\u0bfb\u0bfc\u0bfd\u0bfe\u0bff\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a\u0c3b\u0c3c\u0c3d\u0c45\u0c49\u0c4e\u0c4f\u0c50\u0c51\u0c52\u0c53\u0c54\u0c57\u0c58\u0c59\u0c5a\u0c5b\u0c5c\u0c5d\u0c5e\u0c5f\u0c62\u0c63\u0c64\u0c65\u0c70\u0c71\u0c72\u0c73\u0c74\u0c75\u0c76\u0c77\u0c78\u0c79\u0c7a\u0c7b\u0c7c\u0c7d\u0c7e\u0c7f\u0c80\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba\u0cbb\u0cc5\u0cc9\u0cce\u0ccf\u0cd0\u0cd1\u0cd2\u0cd3\u0cd4\u0cd7\u0cd8\u0cd9\u0cda\u0cdb\u0cdc\u0cdd\u0cdf\u0ce2\u0ce3\u0ce4\u0ce5\u0cf0\u0cf1\u0cf2\u0cf3\u0cf4\u0cf5\u0c
 f6\u0cf7\u0cf8\u0cf9\u0cfa\u0cfb\u0cfc\u0cfd\u0cfe\u0cff\u0d00\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a\u0d3b\u0d3c\u0d3d\u0d44\u0d45\u0d49\u0d4e\u0d4f\u0d50\u0d51\u0d52\u0d53\u0d54\u0d55\u0d56\u0d58\u0d59\u0d5a\u0d5b\u0d5c\u0d5d\u0d5e\u0d5f\u0d62\u0d63\u0d64\u0d65\u0d70\u0d71\u0d72\u0d73\u0d74\u0d75\u0d76\u0d77\u0d78\u0d79\u0d7a\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f\u0d80\u0d81\u0d84\u0d97\u0d98\u0d99\u0db2\u0dbc\u0dbe\u0dbf\u0dc7\u0dc8\u0dc9\u0dcb\u0dcc\u0dcd\u0dce\u0dd5\u0dd7\u0de0\u0de1\u0de2\u0de3\u0de4\u0de5\u0de6\u0de7\u0de8\u0de9\u0dea\u0deb\u0dec\u0ded\u0dee\u0def\u0df0\u0df1\u0df5\u0df6\u0df7\u0df8\u0df9\u0dfa\u0dfb\u0dfc\u0dfd\u0dfe\u0dff\u0e00\u0e3b\u0e3c\u0e3d\u0e3e\u0e5c\u0e5d\u0e5e\u0e5f\u0e60\u0e61\u0e62\u0e63\u0e64\u0e65\u0e66\u0e67\u0e68\u0e69\u0e6a\u0e6b\u0e6c\u0e6d\u0e6e\u0e6f\u0e70\u0e71\u0e72\u0e73\u0e74\u0e75\u0e76\u0e77\u0e78\u0e79\u0e7a\u0e7b\u0e7c\u0e7d\u0e7e\u0e7f\u0e80\u0e83\u0e85\u0e86\u0e89\u0e8b\u0e8c\u0e8e\u0e8f\u0e90\u0e91\u0e92\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea
 8\u0ea9\u0eac\u0eba\u0ebe\u0ebf\u0ec5\u0ec7\u0ece\u0ecf\u0eda\u0edb\u0ede\u0edf\u0ee0\u0ee1\u0ee2\u0ee3\u0ee4\u0ee5\u0ee6\u0ee7\u0ee8\u0ee9\u0eea\u0eeb\u0eec\u0eed\u0eee\u0eef\u0ef0\u0ef1\u0ef2\u0ef3\u0ef4\u0ef5\u0ef6\u0ef7\u0ef8\u0ef9\u0efa\u0efb\u0efc\u0efd\u0efe\u0eff\u0f48\u0f6b\u0f6c\u0f6d\u0f6e\u0f6f\u0f70\u0f8c\u0f8d\u0f8e\u0f8f\u0f98\u0fbd\u0fcd\u0fce\u0fd2\u0fd3\u0fd4\u0fd5\u0fd6\u0fd7\u0fd8\u0fd9\u0fda\u0fdb\u0fdc\u0fdd\u0fde\u0fdf\u0fe0\u0fe1\u0fe2\u0fe3\u0fe4\u0fe5\u0fe6\u0fe7\u0fe8\u0fe9\u0fea\u0feb\u0fec\u0fed\u0fee\u0fef\u0ff0\u0ff1\u0ff2\u0ff3\u0ff4\u0ff5\u0ff6\u0ff7\u0ff8\u0ff9\u0ffa\u0ffb\u0ffc\u0ffd\u0ffe\u0fff\u1022\u1028\u102b\u1033\u1034\u1035\u103a\u103b\u103c\u103d\u103e\u103f\u105a\u105b\u105c\u105d\u105e\u105f\u1060\u1061\u1062\u1063\u1064\u1065\u1066\u1067\u1068\u1069\u106a\u106b\u106c\u106d\u106e\u106f\u1070\u1071\u1072\u1073\u1074\u1075\u1076\u1077\u1078\u1079\u107a\u107b\u107c\u107d\u107e\u107f\u1080\u1081\u1082\u1083\u1084\u1085\u1086\u1087\u1088\u1089
 \u108a\u108b\u108c\u108d\u108e\u108f\u1090\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\u109a\u109b\u109c\u109d\u109e\u109f\u10c6\u10c7\u10c8\u10c9\u10ca\u10cb\u10cc\u10cd\u10ce\u10cf\u10fd\u10fe\u10ff\u115a\u115b\u115c\u115d\u115e\u11a3\u11a4\u11a5\u11a6\u11a7\u11fa\u11fb\u11fc\u11fd\u11fe\u11ff\u1249\u124e\u124f\u1257\u1259\u125e\u125f\u1289\u128e\u128f\u12b1\u12b6\u12b7\u12bf\u12c1\u12c6\u12c7\u12d7\u1311\u1316\u1317\u135b\u135c\u135d\u135e\u137d\u137e\u137f\u139a\u139b\u139c\u139d\u139e\u139f\u13f5\u13f6\u13f7\u13f8\u13f9\u13fa\u13fb\u13fc\u13fd\u13fe\u13ff\u1400\u1677\u1678\u1679\u167a\u167b\u167c\u167d\u167e\u167f\u169d\u169e\u169f\u16f1\u16f2\u16f3\u16f4\u16f5\u16f6\u16f7\u16f8\u16f9\u16fa\u16fb\u16fc\u16fd\u16fe\u16ff\u170d\u1715\u1716\u1717\u1718\u1719\u171a\u171b\u171c\u171d\u171e\u171f\u1737\u1738\u1739\u173a\u173b\u173c\u173d\u173e\u173f\u1754\u1755\u1756\u1757\u1758\u1759\u175a\u175b\u175c\u175d\u175e\u175f\u176d\u1771\u1774\u1775\u1776\u1777\u1778\u1779\u177a\
 u177b\u177c\u177d\u177e\u177f\u17de\u17df\u17ea\u17eb\u17ec\u17ed\u17ee\u17ef\u17fa\u17fb\u17fc\u17fd\u17fe\u17ff\u180f\u181a\u181b\u181c\u181d\u181e\u181f\u1878\u1879\u187a\u187b\u187c\u187d\u187e\u187f\u18aa\u18ab\u18ac\u18ad\u18ae\u18af\u18b0\u18b1\u18b2\u18b3\u18b4\u18b5\u18b6\u18b7\u18b8\u18b9\u18ba\u18bb\u18bc\u18bd\u18be\u18bf\u18c0\u18c1\u18c2\u18c3\u18c4\u18c5\u18c6\u18c7\u18c8\u18c9\u18ca\u18cb\u18cc\u18cd\u18ce\u18cf\u18d0\u18d1\u18d2\u18d3\u18d4\u18d5\u18d6\u18d7\u18d8\u18d9\u18da\u18db\u18dc\u18dd\u18de\u18df\u18e0\u18e1\u18e2\u18e3\u18e4\u18e5\u18e6\u18e7\u18e8\u18e9\u18ea\u18eb\u18ec\u18ed\u18ee\u18ef\u18f0\u18f1\u18f2\u18f3\u18f4\u18f5\u18f6\u18f7\u18f8\u18f9\u18fa\u18fb\u18fc\u18fd\u18fe\u18ff\u191d\u191e\u191f\u192c\u192d\u192e\u192f\u193c\u193d\u193e\u193f\u1941\u1942\u1943\u196e\u196f\u1975\u1976\u1977\u1978\u1979\u197a\u197b\u197c\u197d\u197e\u197f\u19aa\u19ab\u19ac\u19ad\u19ae\u19af\u19ca\u19cb\u19cc\u19cd\u19ce\u19cf\u19da\u19db\u19dc\u19dd\u1a1c\u1a1d\u1a20\u
 1a21\u1a22\u1a23\u1a24\u1a25\u1a26\u1a27\u1a28\u1a29\u1a2a\u1a2b\u1a2c\u1a2d\u1a2e\u1a2f\u1a30\u1a31\u1a32\u1a33\u1a34\u1a35\u1a36\u1a37\u1a38\u1a39\u1a3a\u1a3b\u1a3c\u1a3d\u1a3e\u1a3f\u1a40\u1a41\u1a42\u1a43\u1a44\u1a45\u1a46\u1a47\u1a48\u1a49\u1a4a\u1a4b\u1a4c\u1a4d\u1a4e\u1a4f\u1a50\u1a51\u1a52\u1a53\u1a54\u1a55\u1a56\u1a57\u1a58\u1a59\u1a5a\u1a5b\u1a5c\u1a5d\u1a5e\u1a5f\u1a60\u1a61\u1a62\u1a63\u1a64\u1a65\u1a66\u1a67\u1a68\u1a69\u1a6a\u1a6b\u1a6c\u1a6d\u1a6e\u1a6f\u1a70\u1a71\u1a72\u1a73\u1a74\u1a75\u1a76\u1a77\u1a78\u1a79\u1a7a\u1a7b\u1a7c\u1a7d\u1a7e\u1a7f\u1a80\u1a81\u1a82\u1a83\u1a84\u1a85\u1a86\u1a87\u1a88\u1a89\u1a8a\u1a8b\u1a8c\u1a8d\u1a8e\u1a8f\u1a90\u1a91\u1a92\u1a93\u1a94\u1a95\u1a96\u1a97\u1a98\u1a99\u1a9a\u1a9b\u1a9c\u1a9d\u1a9e\u1a9f\u1aa0\u1aa1\u1aa2\u1aa3\u1aa4\u1aa5\u1aa6\u1aa7\u1aa8\u1aa9\u1aaa\u1aab\u1aac\u1aad\u1aae\u1aaf\u1ab0\u1ab1\u1ab2\u1ab3\u1ab4\u1ab5\u1ab6\u1ab7\u1ab8\u1ab9\u1aba\u1abb\u1abc\u1abd\u1abe\u1abf\u1ac0\u1ac1\u1ac2\u1ac3\u1ac4\u1ac5\u1ac6\u1
 ac7\u1ac8\u1ac9\u1aca\u1acb\u1acc\u1acd\u1ace\u1acf\u1ad0\u1ad1\u1ad2\u1ad3\u1ad4\u1ad5\u1ad6\u1ad7\u1ad8\u1ad9\u1ada\u1adb\u1adc\u1add\u1ade\u1adf\u1ae0\u1ae1\u1ae2\u1ae3\u1ae4\u1ae5\u1ae6\u1ae7\u1ae8\u1ae9\u1aea\u1aeb\u1aec\u1aed\u1aee\u1aef\u1af0\u1af1\u1af2\u1af3\u1af4\u1af5\u1af6\u1af7\u1af8\u1af9\u1afa\u1afb\u1afc\u1afd\u1afe\u1aff\u1b00\u1b01\u1b02\u1b03\u1b04\u1b05\u1b06\u1b07\u1b08\u1b09\u1b0a\u1b0b\u1b0c\u1b0d\u1b0e\u1b0f\u1b10\u1b11\u1b12\u1b13\u1b14\u1b15\u1b16\u1b17\u1b18\u1b19\u1b1a\u1b1b\u1b1c\u1b1d\u1b1e\u1b1f\u1b20\u1b21\u1b22\u1b23\u1b24\u1b25\u1b26\u1b27\u1b28\u1b29\u1b2a\u1b2b\u1b2c\u1b2d\u1b2e\u1b2f\u1b30\u1b31\u1b32\u1b33\u1b34\u1b35\u1b36\u1b37\u1b38\u1b39\u1b3a\u1b3b\u1b3c\u1b3d\u1b3e\u1b3f\u1b40\u1b41\u1b42\u1b43\u1b44\u1b45\u1b46\u1b47\u1b48\u1b49\u1b4a\u1b4b\u1b4c\u1b4d\u1b4e\u1b4f\u1b50\u1b51\u1b52\u1b53\u1b54\u1b55\u1b56\u1b57\u1b58\u1b59\u1b5a\u1b5b\u1b5c\u1b5d\u1b5e\u1b5f\u1b60\u1b61\u1b62\u1b63\u1b64\u1b65\u1b66\u1b67\u1b68\u1b69\u1b6a\u1b6b\u1b6c\u1b
 6d\u1b6e\u1b6f\u1b70\u1b71\u1b72\u1b73\u1b74\u1b75\u1b76\u1b77\u1b78\u1b79\u1b7a\u1b7b\u1b7c\u1b7d\u1b7e\u1b7f\u1b80\u1b81\u1b82\u1b83\u1b84\u1b85\u1b86\u1b87\u1b88\u1b89\u1b8a\u1b8b\u1b8c\u1b8d\u1b8e\u1b8f\u1b90\u1b91\u1b92\u1b93\u1b94\u1b95\u1b96\u1b97\u1b98\u1b99\u1b9a\u1b9b\u1b9c\u1b9d\u1b9e\u1b9f\u1ba0\u1ba1\u1ba2\u1ba3\u1ba4\u1ba5\u1ba6\u1ba7\u1ba8\u1ba9\u1baa\u1bab\u1bac\u1bad\u1bae\u1baf\u1bb0\u1bb1\u1bb2\u1bb3\u1bb4\u1bb5\u1bb6\u1bb7\u1bb8\u1bb9\u1bba\u1bbb\u1bbc\u1bbd\u1bbe\u1bbf\u1bc0\u1bc1\u1bc2\u1bc3\u1bc4\u1bc5\u1bc6\u1bc7\u1bc8\u1bc9\u1bca\u1bcb\u1bcc\u1bcd\u1bce\u1bcf\u1bd0\u1bd1\u1bd2\u1bd3\u1bd4\u1bd5\u1bd6\u1bd7\u1bd8\u1bd9\u1bda\u1bdb\u1bdc\u1bdd\u1bde\u1bdf\u1be0\u1be1\u1be2\u1be3\u1be4\u1be5\u1be6\u1be7\u1be8\u1be9\u1bea\u1beb\u1bec\u1bed\u1bee\u1bef\u1bf0\u1bf1\u1bf2\u1bf3\u1bf4\u1bf5\u1bf6\u1bf7\u1bf8\u1bf9\u1bfa\u1bfb\u1bfc\u1bfd\u1bfe\u1bff\u1c00\u1c01\u1c02\u1c03\u1c04\u1c05\u1c06\u1c07\u1c08\u1c09\u1c0a\u1c0b\u1c0c\u1c0d\u1c0e\u1c0f\u1c10\u1c11\u1c12\u1c1
 3\u1c14\u1c15\u1c16\u1c17\u1c18\u1c19\u1c1a\u1c1b\u1c1c\u1c1d\u1c1e\u1c1f\u1c20\u1c21\u1c22\u1c23\u1c24\u1c25\u1c26\u1c27\u1c28\u1c29\u1c2a\u1c2b\u1c2c\u1c2d\u1c2e\u1c2f\u1c30\u1c31\u1c32\u1c33\u1c34\u1c35\u1c36\u1c37\u1c38\u1c39\u1c3a\u1c3b\u1c3c\u1c3d\u1c3e\u1c3f\u1c40\u1c41\u1c42\u1c43\u1c44\u1c45\u1c46\u1c47\u1c48\u1c49\u1c4a\u1c4b\u1c4c\u1c4d\u1c4e\u1c4f\u1c50\u1c51\u1c52\u1c53\u1c54\u1c55\u1c56\u1c57\u1c58\u1c59\u1c5a\u1c5b\u1c5c\u1c5d\u1c5e\u1c5f\u1c60\u1c61\u1c62\u1c63\u1c64\u1c65\u1c66\u1c67\u1c68\u1c69\u1c6a\u1c6b\u1c6c\u1c6d\u1c6e\u1c6f\u1c70\u1c71\u1c72\u1c73\u1c74\u1c75\u1c76\u1c77\u1c78\u1c79\u1c7a\u1c7b\u1c7c\u1c7d\u1c7e\u1c7f\u1c80\u1c81\u1c82\u1c83\u1c84\u1c85\u1c86\u1c87\u1c88\u1c89\u1c8a\u1c8b\u1c8c\u1c8d\u1c8e\u1c8f\u1c90\u1c91\u1c92\u1c93\u1c94\u1c95\u1c96\u1c97\u1c98\u1c99\u1c9a\u1c9b\u1c9c\u1c9d\u1c9e\u1c9f\u1ca0\u1ca1\u1ca2\u1ca3\u1ca4\u1ca5\u1ca6\u1ca7\u1ca8\u1ca9\u1caa\u1cab\u1cac\u1cad\u1cae\u1caf\u1cb0\u1cb1\u1cb2\u1cb3\u1cb4\u1cb5\u1cb6\u1cb7\u1cb8\u1cb9
 \u1cba\u1cbb\u1cbc\u1cbd\u1cbe\u1cbf\u1cc0\u1cc1\u1cc2\u1cc3\u1cc4\u1cc5\u1cc6\u1cc7\u1cc8\u1cc9\u1cca\u1ccb\u1ccc\u1ccd\u1cce\u1ccf\u1cd0\u1cd1\u1cd2\u1cd3\u1cd4\u1cd5\u1cd6\u1cd7\u1cd8\u1cd9\u1cda\u1cdb\u1cdc\u1cdd\u1cde\u1cdf\u1ce0\u1ce1\u1ce2\u1ce3\u1ce4\u1ce5\u1ce6\u1ce7\u1ce8\u1ce9\u1cea\u1ceb\u1cec\u1ced\u1cee\u1cef\u1cf0\u1cf1\u1cf2\u1cf3\u1cf4\u1cf5\u1cf6\u1cf7\u1cf8\u1cf9\u1cfa\u1cfb\u1cfc\u1cfd\u1cfe\u1cff\u1dc4\u1dc5\u1dc6\u1dc7\u1dc8\u1dc9\u1dca\u1dcb\u1dcc\u1dcd\u1dce\u1dcf\u1dd0\u1dd1\u1dd2\u1dd3\u1dd4\u1dd5\u1dd6\u1dd7\u1dd8\u1dd9\u1dda\u1ddb\u1ddc\u1ddd\u1dde\u1ddf\u1de0\u1de1\u1de2\u1de3\u1de4\u1de5\u1de6\u1de7\u1de8\u1de9\u1dea\u1deb\u1dec\u1ded\u1dee\u1def\u1df0\u1df1\u1df2\u1df3\u1df4\u1df5\u1df6\u1df7\u1df8\u1df9\u1dfa\u1dfb\u1dfc\u1dfd\u1dfe\u1dff\u1e9c\u1e9d\u1e9e\u1e9f\u1efa\u1efb\u1efc\u1efd\u1efe\u1eff\u1f16\u1f17\u1f1e\u1f1f\u1f46\u1f47\u1f4e\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e\u1f7f\u1fb5\u1fc5\u1fd4\u1fd5\u1fdc\u1ff0\u1ff1\u1ff5\u1fff\u2064\u2065\u2066\
 u2067\u2068\u2069\u2072\u2073\u208f\u2095\u2096\u2097\u2098\u2099\u209a\u209b\u209c\u209d\u209e\u209f\u20b6\u20b7\u20b8\u20b9\u20ba\u20bb\u20bc\u20bd\u20be\u20bf\u20c0\u20c1\u20c2\u20c3\u20c4\u20c5\u20c6\u20c7\u20c8\u20c9\u20ca\u20cb\u20cc\u20cd\u20ce\u20cf\u20ec\u20ed\u20ee\u20ef\u20f0\u20f1\u20f2\u20f3\u20f4\u20f5\u20f6\u20f7\u20f8\u20f9\u20fa\u20fb\u20fc\u20fd\u20fe\u20ff\u214d\u214e\u214f\u2150\u2151\u2152\u2184\u2185\u2186\u2187\u2188\u2189\u218a\u218b\u218c\u218d\u218e\u218f\u23dc\u23dd\u23de\u23df\u23e0\u23e1\u23e2\u23e3\u23e4\u23e5\u23e6\u23e7\u23e8\u23e9\u23ea\u23eb\u23ec\u23ed\u23ee\u23ef\u23f0\u23f1\u23f2\u23f3\u23f4\u23f5\u23f6\u23f7\u23f8\u23f9\u23fa\u23fb\u23fc\u23fd\u23fe\u23ff\u2427\u2428\u2429\u242a\u242b\u242c\u242d\u242e\u242f\u2430\u2431\u2432\u2433\u2434\u2435\u2436\u2437\u2438\u2439\u243a\u243b\u243c\u243d\u243e\u243f\u244b\u244c\u244d\u244e\u244f\u2450\u2451\u2452\u2453\u2454\u2455\u2456\u2457\u2458\u2459\u245a\u245b\u245c\u245d\u245e\u245f\u269d\u269e\u269f\u
 26b2\u26b3\u26b4\u26b5\u26b6\u26b7\u26b8\u26b9\u26ba\u26bb\u26bc\u26bd\u26be\u26bf\u26c0\u26c1\u26c2\u26c3\u26c4\u26c5\u26c6\u26c7\u26c8\u26c9\u26ca\u26cb\u26cc\u26cd\u26ce\u26cf\u26d0\u26d1\u26d2\u26d3\u26d4\u26d5\u26d6\u26d7\u26d8\u26d9\u26da\u26db\u26dc\u26dd\u26de\u26df\u26e0\u26e1\u26e2\u26e3\u26e4\u26e5\u26e6\u26e7\u26e8\u26e9\u26ea\u26eb\u26ec\u26ed\u26ee\u26ef\u26f0\u26f1\u26f2\u26f3\u26f4\u26f5\u26f6\u26f7\u26f8\u26f9\u26fa\u26fb\u26fc\u26fd\u26fe\u26ff\u2700\u2705\u270a\u270b\u2728\u274c\u274e\u2753\u2754\u2755\u2757\u275f\u2760\u2795\u2796\u2797\u27b0\u27bf\u27c7\u27c8\u27c9\u27ca\u27cb\u27cc\u27cd\u27ce\u27cf\u27ec\u27ed\u27ee\u27ef\u2b14\u2b15\u2b16\u2b17\u2b18\u2b19\u2b1a\u2b1b\u2b1c\u2b1d\u2b1e\u2b1f\u2b20\u2b21\u2b22\u2b23\u2b24\u2b25\u2b26\u2b27\u2b28\u2b29\u2b2a\u2b2b\u2b2c\u2b2d\u2b2e\u2b2f\u2b30\u2b31\u2b32\u2b33\u2b34\u2b35\u2b36\u2b37\u2b38\u2b39\u2b3a\u2b3b\u2b3c\u2b3d\u2b3e\u2b3f\u2b40\u2b41\u2b42\u2b43\u2b44\u2b45\u2b46\u2b47\u2b48\u2b49\u2b4a\u2b4b\u2b4c\u2
 b4d\u2b4e\u2b4f\u2b50\u2b51\u2b52\u2b53\u2b54\u2b55\u2b56\u2b57\u2b58\u2b59\u2b5a\u2b5b\u2b5c\u2b5d\u2b5e\u2b5f\u2b60\u2b61\u2b62\u2b63\u2b64\u2b65\u2b66\u2b67\u2b68\u2b69\u2b6a\u2b6b\u2b6c\u2b6d\u2b6e\u2b6f\u2b70\u2b71\u2b72\u2b73\u2b74\u2b75\u2b76\u2b77\u2b78\u2b79\u2b7a\u2b7b\u2b7c\u2b7d\u2b7e\u2b7f\u2b80\u2b81\u2b82\u2b83\u2b84\u2b85\u2b86\u2b87\u2b88\u2b89\u2b8a\u2b8b\u2b8c\u2b8d\u2b8e\u2b8f\u2b90\u2b91\u2b92\u2b93\u2b94\u2b95\u2b96\u2b97\u2b98\u2b99\u2b9a\u2b9b\u2b9c\u2b9d\u2b9e\u2b9f\u2ba0\u2ba1\u2ba2\u2ba3\u2ba4\u2ba5\u2ba6\u2ba7\u2ba8\u2ba9\u2baa\u2bab\u2bac\u2bad\u2bae\u2baf\u2bb0\u2bb1\u2bb2\u2bb3\u2bb4\u2bb5\u2bb6\u2bb7\u2bb8\u2bb9\u2bba\u2bbb\u2bbc\u2bbd\u2bbe\u2bbf\u2bc0\u2bc1\u2bc2\u2bc3\u2bc4\u2bc5\u2bc6\u2bc7\u2bc8\u2bc9\u2bca\u2bcb\u2bcc\u2bcd\u2bce\u2bcf\u2bd0\u2bd1\u2bd2\u2bd3\u2bd4\u2bd5\u2bd6\u2bd7\u2bd8\u2bd9\u2bda\u2bdb\u2bdc\u2bdd\u2bde\u2bdf\u2be0\u2be1\u2be2\u2be3\u2be4\u2be5\u2be6\u2be7\u2be8\u2be9\u2bea\u2beb\u2bec\u2bed\u2bee\u2bef\u2bf0\u2bf1\u2bf2\u2b
 f3\u2bf4\u2bf5\u2bf6\u2bf7\u2bf8\u2bf9\u2bfa\u2bfb\u2bfc\u2bfd\u2bfe\u2bff\u2c2f\u2c5f\u2c60\u2c61\u2c62\u2c63\u2c64\u2c65\u2c66\u2c67\u2c68\u2c69\u2c6a\u2c6b\u2c6c\u2c6d\u2c6e\u2c6f\u2c70\u2c71\u2c72\u2c73\u2c74\u2c75\u2c76\u2c77\u2c78\u2c79\u2c7a\u2c7b\u2c7c\u2c7d\u2c7e\u2c7f\u2ceb\u2cec\u2ced\u2cee\u2cef\u2cf0\u2cf1\u2cf2\u2cf3\u2cf4\u2cf5\u2cf6\u2cf7\u2cf8\u2d26\u2d27\u2d28\u2d29\u2d2a\u2d2b\u2d2c\u2d2d\u2d2e\u2d2f\u2d66\u2d67\u2d68\u2d69\u2d6a\u2d6b\u2d6c\u2d6d\u2d6e\u2d70\u2d71\u2d72\u2d73\u2d74\u2d75\u2d76\u2d77\u2d78\u2d79\u2d7a\u2d7b\u2d7c\u2d7d\u2d7e\u2d7f\u2d97\u2d98\u2d99\u2d9a\u2d9b\u2d9c\u2d9d\u2d9e\u2d9f\u2da7\u2daf\u2db7\u2dbf\u2dc7\u2dcf\u2dd7\u2ddf\u2de0\u2de1\u2de2\u2de3\u2de4\u2de5\u2de6\u2de7\u2de8\u2de9\u2dea\u2deb\u2dec\u2ded\u2dee\u2def\u2df0\u2df1\u2df2\u2df3\u2df4\u2df5\u2df6\u2df7\u2df8\u2df9\u2dfa\u2dfb\u2dfc\u2dfd\u2dfe\u2dff\u2e18\u2e19\u2e1a\u2e1b\u2e1e\u2e1f\u2e20\u2e21\u2e22\u2e23\u2e24\u2e25\u2e26\u2e27\u2e28\u2e29\u2e2a\u2e2b\u2e2c\u2e2d\u2e2e\u2e2
 f\u2e30\u2e31\u2e32\u2e33\u2e34\u2e35\u2e36\u2e37\u2e38\u2e39\u2e3a\u2e3b\u2e3c\u2e3d\u2e3e\u2e3f\u2e40\u2e41\u2e42\u2e43\u2e44\u2e45\u2e46\u2e47\u2e48\u2e49\u2e4a\u2e4b\u2e4c\u2e4d\u2e4e\u2e4f\u2e50\u2e51\u2e52\u2e53\u2e54\u2e55\u2e56\u2e57\u2e58\u2e59\u2e5a\u2e5b\u2e5c\u2e5d\u2e5e\u2e5f\u2e60\u2e61\u2e62\u2e63\u2e64\u2e65\u2e66\u2e67\u2e68\u2e69\u2e6a\u2e6b\u2e6c\u2e6d\u2e6e\u2e6f\u2e70\u2e71\u2e72\u2e73\u2e74\u2e75\u2e76\u2e77\u2e78\u2e79\u2e7a\u2e7b\u2e7c\u2e7d\u2e7e\u2e7f\u2e9a\u2ef4\u2ef5\u2ef6\u2ef7\u2ef8\u2ef9\u2efa\u2efb\u2efc\u2efd\u2efe\u2eff\u2fd6\u2fd7\u2fd8\u2fd9\u2fda\u2fdb\u2fdc\u2fdd\u2fde\u2fdf\u2fe0\u2fe1\u2fe2\u2fe3\u2fe4\u2fe5\u2fe6\u2fe7\u2fe8\u2fe9\u2fea\u2feb\u2fec\u2fed\u2fee\u2fef\u2ffc\u2ffd\u2ffe\u2fff\u3040\u3097\u3098\u3100\u3101\u3102\u3103\u3104\u312d\u312e\u312f\u3130\u318f\u31b8\u31b9\u31ba\u31bb\u31bc\u31bd\u31be\u31bf\u31d0\u31d1\u31d2\u31d3\u31d4\u31d5\u31d6\u31d7\u31d8\u31d9\u31da\u31db\u31dc\u31dd\u31de\u31df\u31e0\u31e1\u31e2\u31e3\u31e4\u31e5
 \u31e6\u31e7\u31e8\u31e9\u31ea\u31eb\u31ec\u31ed\u31ee\u31ef\u321f\u3244\u3245\u3246\u3247\u3248\u3249\u324a\u324b\u324c\u324d\u324e\u324f\u32ff\u4db6\u4db7\u4db8\u4db9\u4dba\u4dbb\u4dbc\u4dbd\u4dbe\u4dbf\u9fbc\u9fbd\u9fbe\u9fbf\u9fc0\u9fc1\u9fc2\u9fc3\u9fc4\u9fc5\u9fc6\u9fc7\u9fc8\u9fc9\u9fca\u9fcb\u9fcc\u9fcd\u9fce\u9fcf\u9fd0\u9fd1\u9fd2\u9fd3\u9fd4\u9fd5\u9fd6\u9fd7\u9fd8\u9fd9\u9fda\u9fdb\u9fdc\u9fdd\u9fde\u9fdf\u9fe0\u9fe1\u9fe2\u9fe3\u9fe4\u9fe5\u9fe6\u9fe7\u9fe8\u9fe9\u9fea\u9feb\u9fec\u9fed\u9fee\u9fef\u9ff0\u9ff1\u9ff2\u9ff3\u9ff4\u9ff5\u9ff6\u9ff7\u9ff8\u9ff9\u9ffa\u9ffb\u9ffc\u9ffd\u9ffe\u9fff\ua48d\ua48e\ua48f\ua4c7\ua4c8\ua4c9\ua4ca\ua4cb\ua4cc\ua4cd\ua4ce\ua4cf\ua4d0\ua4d1\ua4d2\ua4d3\ua4d4\ua4d5\ua4d6\ua4d7\ua4d8\ua4d9\ua4da\ua4db\ua4dc\ua4dd\ua4de\ua4df\ua4e0\ua4e1\ua4e2\ua4e3\ua4e4\ua4e5\ua4e6\ua4e7\ua4e8\ua4e9\ua4ea\ua4eb\ua4ec\ua4ed\ua4ee\ua4ef\ua4f0\ua4f1\ua4f2\ua4f3\ua4f4\ua4f5\ua4f6\ua4f7\ua4f8\ua4f9\ua4fa\ua4fb\ua4fc\ua4fd\ua4fe\ua4ff\ua500\ua501\ua502\ua503\
 ua504\ua505\ua506\ua507\ua508\ua509\ua50a\ua50b\ua50c\ua50d\ua50e\ua50f\ua510\ua511\ua512\ua513\ua514\ua515\ua516\ua517\ua518\ua519\ua51a\ua51b\ua51c\ua51d\ua51e\ua51f\ua520\ua521\ua522\ua523\ua524\ua525\ua526\ua527\ua528\ua529\ua52a\ua52b\ua52c\ua52d\ua52e\ua52f\ua530\ua531\ua532\ua533\ua534\ua535\ua536\ua537\ua538\ua539\ua53a\ua53b\ua53c\ua53d\ua53e\ua53f\ua540\ua541\ua542\ua543\ua544\ua545\ua546\ua547\ua548\ua549\ua54a\ua54b\ua54c\ua54d\ua54e\ua54f\ua550\ua551\ua552\ua553\ua554\ua555\ua556\ua557\ua558\ua559\ua55a\ua55b\ua55c\ua55d\ua55e\ua55f\ua560\ua561\ua562\ua563\ua564\ua565\ua566\ua567\ua568\ua569\ua56a\ua56b\ua56c\ua56d\ua56e\ua56f\ua570\ua571\ua572\ua573\ua574\ua575\ua576\ua577\ua578\ua579\ua57a\ua57b\ua57c\ua57d\ua57e\ua57f\ua580\ua581\ua582\ua583\ua584\ua585\ua586\ua587\ua588\ua589\ua58a\ua58b\ua58c\ua58d\ua58e\ua58f\ua590\ua591\ua592\ua593\ua594\ua595\ua596\ua597\ua598\ua599\ua59a\ua59b\ua59c\ua59d\ua59e\ua59f\ua5a0\ua5a1\ua5a2\ua5a3\ua5a4\ua5a5\ua5a6\ua5a7\ua5a8\ua5a9\u
 a5aa\ua5ab\ua5ac\ua5ad\ua5ae\ua5af\ua5b0\ua5b1\ua5b2\ua5b3\ua5b4\ua5b5\ua5b6\ua5b7\ua5b8\ua5b9\ua5ba\ua5bb\ua5bc\ua5bd\ua5be\ua5bf\ua5c0\ua5c1\ua5c2\ua5c3\ua5c4\ua5c5\ua5c6\ua5c7\ua5c8\ua5c9\ua5ca\ua5cb\ua5cc\ua5cd\ua5ce\ua5cf\ua5d0\ua5d1\ua5d2\ua5d3\ua5d4\ua5d5\ua5d6\ua5d7\ua5d8\ua5d9\ua5da\ua5db\ua5dc\ua5dd\ua5de\ua5df\ua5e0\ua5e1\ua5e2\ua5e3\ua5e4\ua5e5\ua5e6\ua5e7\ua5e8\ua5e9\ua5ea\ua5eb\ua5ec\ua5ed\ua5ee\ua5ef\ua5f0\ua5f1\ua5f2\ua5f3\ua5f4\ua5f5\ua5f6\ua5f7\ua5f8\ua5f9\ua5fa\ua5fb\ua5fc\ua5fd\ua5fe\ua5ff\ua600\ua601\ua602\ua603\ua604\ua605\ua606\ua607\ua608\ua609\ua60a\ua60b\ua60c\ua60d\ua60e\ua60f\ua610\ua611\ua612\ua613\ua614\ua615\ua616\ua617\ua618\ua619\ua61a\ua61b\ua61c\ua61d\ua61e\ua61f\ua620\ua621\ua622\ua623\ua624\ua625\ua626\ua627\ua628\ua629\ua62a\ua62b\ua62c\ua62d\ua62e\ua62f\ua630\ua631\ua632\ua633\ua634\ua635\ua636\ua637\ua638\ua639\ua63a\ua63b\ua63c\ua63d\ua63e\ua63f\ua640\ua641\ua642\ua643\ua644\ua645\ua646\ua647\ua648\ua649\ua64a\ua64b\ua64c\ua64d\ua64e\ua64f\ua
 650\ua651\ua652\ua653\ua654\ua655\ua656\ua657\ua658\ua659\ua65a\ua65b\ua65c\ua65d\ua65e\ua65f\ua660\ua661\ua662\ua663\ua664\ua665\ua666\ua667\ua668\ua669\ua66a\ua66b\ua66c\ua66d\ua66e\ua66f\ua670\ua671\ua672\ua673\ua674\ua675\ua676\ua677\ua678\ua679\ua67a\ua67b\ua67c\ua67d\ua67e\ua67f\ua680\ua681\ua682\ua683\ua684\ua685\ua686\ua687\ua688\ua689\ua68a\ua68b\ua68c\ua68d\ua68e\ua68f\ua690\ua691\ua692\ua693\ua694\ua695\ua696\ua697\ua698\ua699\ua69a\ua69b\ua69c\ua69d\ua69e\ua69f\ua6a0\ua6a1\ua6a2\ua6a3\ua6a4\ua6a5\ua6a6\ua6a7\ua6a8\ua6a9\ua6aa\ua6ab\ua6ac\ua6ad\ua6ae\ua6af\ua6b0\ua6b1\ua6b2\ua6b3\ua6b4\ua6b5\ua6b6\ua6b7\ua6b8\ua6b9\ua6ba\ua6bb\ua6bc\ua6bd\ua6be\ua6bf\ua6c0\ua6c1\ua6c2\ua6c3\ua6c4\ua6c5\ua6c6\ua6c7\ua6c8\ua6c9\ua6ca\ua6cb\ua6cc\ua6cd\ua6ce\ua6cf\ua6d0\ua6d1\ua6d2\ua6d3\ua6d4\ua6d5\ua6d6\ua6d7\ua6d8\ua6d9\ua6da\ua6db\ua6dc\ua6dd\ua6de\ua6df\ua6e0\ua6e1\ua6e2\ua6e3\ua6e4\ua6e5\ua6e6\ua6e7\ua6e8\ua6e9\ua6ea\ua6eb\ua6ec\ua6ed\ua6ee\ua6ef\ua6f0\ua6f1\ua6f2\ua6f3\ua6f4\ua6f5\ua6
 f6\ua6f7\ua6f8\ua6f9\ua6fa\ua6fb\ua6fc\ua6fd\ua6fe\ua6ff\ua717\ua718\ua719\ua71a\ua71b\ua71c\ua71d\ua71e\ua71f\ua720\ua721\ua722\ua723\ua724\ua725\ua726\ua727\ua728\ua729\ua72a\ua72b\ua72c\ua72d\ua72e\ua72f\ua730\ua731\ua732\ua733\ua734\ua735\ua736\ua737\ua738\ua739\ua73a\ua73b\ua73c\ua73d\ua73e\ua73f\ua740\ua741\ua742\ua743\ua744\ua745\ua746\ua747\ua748\ua749\ua74a\ua74b\ua74c\ua74d\ua74e\ua74f\ua750\ua751\ua752\ua753\ua754\ua755\ua756\ua757\ua758\ua759\ua75a\ua75b\ua75c\ua75d\ua75e\ua75f\ua760\ua761\ua762\ua763\ua764\ua765\ua766\ua767\ua768\ua769\ua76a\ua76b\ua76c\ua76d\ua76e\ua76f\ua770\ua771\ua772\ua773\ua774\ua775\ua776\ua777\ua778\ua779\ua77a\ua77b\ua77c\ua77d\ua77e\ua77f\ua780\ua781\ua782\ua783\ua784\ua785\ua786\ua787\ua788\ua789\ua78a\ua78b\ua78c\ua78d\ua78e\ua78f\ua790\ua791\ua792\ua793\ua794\ua795\ua796\ua797\ua798\ua799\ua79a\ua79b\ua79c\ua79d\ua79e\ua79f\ua7a0\ua7a1\ua7a2\ua7a3\ua7a4\ua7a5\ua7a6\ua7a7\ua7a8\ua7a9\ua7aa\ua7ab\ua7ac\ua7ad\ua7ae\ua7af\ua7b0\ua7b1\ua7b2\ua7b
 3\ua7b4\ua7b5\ua7b6\ua7b7\ua7b8\ua7b9\ua7ba\ua7bb\ua7bc\ua7bd\ua7be\ua7bf\ua7c0\ua7c1\ua7c2\ua7c3\ua7c4\ua7c5\ua7c6\ua7c7\ua7c8\ua7c9\ua7ca\ua7cb\ua7cc\ua7cd\ua7ce\ua7cf\ua7d0\ua7d1\ua7d2\ua7d3\ua7d4\ua7d5\ua7d6\ua7d7\ua7d8\ua7d9\ua7da\ua7db\ua7dc\ua7dd\ua7de\ua7df\ua7e0\ua7e1\ua7e2\ua7e3\ua7e4\ua7e5\ua7e6\ua7e7\ua7e8\ua7e9\ua7ea\ua7eb\ua7ec\ua7ed\ua7ee\ua7ef\ua7f0\ua7f1\ua7f2\ua7f3\ua7f4\ua7f5\ua7f6\ua7f7\ua7f8\ua7f9\ua7fa\ua7fb\ua7fc\ua7fd\ua7fe\ua7ff\ua82c\ua82d\ua82e\ua82f\ua830\ua831\ua832\ua833\ua834\ua835\ua836\ua837\ua838\ua839\ua83a\ua83b\ua83c\ua83d\ua83e\ua83f\ua840\ua841\ua842\ua843\ua844\ua845\ua846\ua847\ua848\ua849\ua84a\ua84b\ua84c\ua84d\ua84e\ua84f\ua850\ua851\ua852\ua853\ua854\ua855\ua856\ua857\ua858\ua859\ua85a\ua85b\ua85c\ua85d\ua85e\ua85f\ua860\ua861\ua862\ua863\ua864\ua865\ua866\ua867\ua868\ua869\ua86a\ua86b\ua86c\ua86d\ua86e\ua86f\ua870\ua871\ua872\ua873\ua874\ua875\ua876\ua877\ua878\ua879\ua87a\ua87b\ua87c\ua87d\ua87e\ua87f\ua880\ua881\ua882\ua883\ua884\ua885
 \ua886\ua887\ua888\ua889\ua88a\ua88b\ua88c\ua88d\ua88e\ua88f\ua890\ua891\ua892\ua893\ua894\ua895\ua896\ua897\ua898\ua899\ua89a\ua89b\ua89c\ua89d\ua89e\ua89f\ua8a0\ua8a1\ua8a2\ua8a3\ua8a4\ua8a5\ua8a6\ua8a7\ua8a8\ua8a9\ua8aa\ua8ab\ua8ac\ua8ad\ua8ae\ua8af\ua8b0\ua8b1\ua8b2\ua8b3\ua8b4\ua8b5\ua8b6\ua8b7\ua8b8\ua8b9\ua8ba\ua8bb\ua8bc\ua8bd\ua8be\ua8bf\ua8c0\ua8c1\ua8c2\ua8c3\ua8c4\ua8c5\ua8c6\ua8c7\ua8c8\ua8c9\ua8ca\ua8cb\ua8cc\ua8cd\ua8ce\ua8cf\ua8d0\ua8d1\ua8d2\ua8d3\ua8d4\ua8d5\ua8d6\ua8d7\ua8d8\ua8d9\ua8da\ua8db\ua8dc\ua8dd\ua8de\ua8df\ua8e0\ua8e1\ua8e2\ua8e3\ua8e4\ua8e5\ua8e6\ua8e7\ua8e8\ua8e9\ua8ea\ua8eb\ua8ec\ua8ed\ua8ee\ua8ef\ua8f0\ua8f1\ua8f2\ua8f3\ua8f4\ua8f5\ua8f6\ua8f7\ua8f8\ua8f9\ua8fa\ua8fb\ua8fc\ua8fd\ua8fe\ua8ff\ua900\ua901\ua902\ua903\ua904\ua905\ua906\ua907\ua908\ua909\ua90a\ua90b\ua90c\ua90d\ua90e\ua90f\ua910\ua911\ua912\ua913\ua914\ua915\ua916\ua917\ua918\ua919\ua91a\ua91b\ua91c\ua91d\ua91e\ua91f\ua920\ua921\ua922\ua923\ua924\ua925\ua926\ua927\ua928\ua929\ua92a\ua92b\
 ua92c\ua92d\ua92e\ua92f\ua930\ua931\ua932\ua933\ua934\ua935\ua936\ua937\ua938\ua939\ua93a\ua93b\ua93c\ua93d\ua93e\ua93f\ua940\ua941\ua942\ua943\ua944\ua945\ua946\ua947\ua948\ua949\ua94a\ua94b\ua94c\ua94d\ua94e\ua94f\ua950\ua951\ua952\ua953\ua954\ua955\ua956\ua957\ua958\ua959\ua95a\ua95b\ua95c\ua95d\ua95e\ua95f\ua960\ua961\ua962\ua963\ua964\ua965\ua966\ua967\ua968\ua969\ua96a\ua96b\ua96c\ua96d\ua96e\ua96f\ua970\ua971\ua972\ua973\ua974\ua975\ua976\ua977\ua978\ua979\ua97a\ua97b\ua97c\ua97d\ua97e\ua97f\ua980\ua981\ua982\ua983\ua984\ua985\ua986\ua987\ua988\ua989\ua98a\ua98b\ua98c\ua98d\ua98e\ua98f\ua990\ua991\ua992\ua993\ua994\ua995\ua996\ua997\ua998\ua999\ua99a\ua99b\ua99c\ua99d\ua99e\ua99f\ua9a0\ua9a1\ua9a2\ua9a3\ua9a4\ua9a5\ua9a6\ua9a7\ua9a8\ua9a9\ua9aa\ua9ab\ua9ac\ua9ad\ua9ae\ua9af\ua9b0\ua9b1\ua9b2\ua9b3\ua9b4\ua9b5\ua9b6\ua9b7\ua9b8\ua9b9\ua9ba\ua9bb\ua9bc\ua9bd\ua9be\ua9bf\ua9c0\ua9c1\ua9c2\ua9c3\ua9c4\ua9c5\ua9c6\ua9c7\ua9c8\ua9c9\ua9ca\ua9cb\ua9cc\ua9cd\ua9ce\ua9cf\ua9d0\ua9d1\u
 a9d2\ua9d3\ua9d4\ua9d5\ua9d6\ua9d7\ua9d8\ua9d9\ua9da\ua9db\ua9dc\ua9dd\ua9de\ua9df\ua9e0\ua9e1\ua9e2\ua9e3\ua9e4\ua9e5\ua9e6\ua9e7\ua9e8\ua9e9\ua9ea\ua9eb\ua9ec\ua9ed\ua9ee\ua9ef\ua9f0\ua9f1\ua9f2\ua9f3\ua9f4\ua9f5\ua9f6\ua9f7\ua9f8\ua9f9\ua9fa\ua9fb\ua9fc\ua9fd\ua9fe\ua9ff\uaa00\uaa01\uaa02\uaa03\uaa04\uaa05\uaa06\uaa07\uaa08\uaa09\uaa0a\uaa0b\uaa0c\uaa0d\uaa0e\uaa0f\uaa10\uaa11\uaa12\uaa13\uaa14\uaa15\uaa16\uaa17\uaa18\uaa19\uaa1a\uaa1b\uaa1c\uaa1d\uaa1e\uaa1f\uaa20\uaa21\uaa22\uaa23\uaa24\uaa25\uaa26\uaa27\uaa28\uaa29\uaa2a\uaa2b\uaa2c\uaa2d\uaa2e\uaa2f\uaa30\uaa31\uaa32\uaa33\uaa34\uaa35\uaa36\uaa37\uaa38\uaa39\uaa3a\uaa3b\uaa3c\uaa3d\uaa3e\uaa3f\uaa40\uaa41\uaa42\uaa43\uaa44\uaa45\uaa46\uaa47\uaa48\uaa49\uaa4a\uaa4b\uaa4c\uaa4d\uaa4e\uaa4f\uaa50\uaa51\uaa52\uaa53\uaa54\uaa55\uaa56\uaa57\uaa58\uaa59\uaa5a\uaa5b\uaa5c\uaa5d\uaa5e\uaa5f\uaa60\uaa61\uaa62\uaa63\uaa64\uaa65\uaa66\uaa67\uaa68\uaa69\uaa6a\uaa6b\uaa6c\uaa6d\uaa6e\uaa6f\uaa70\uaa71\uaa72\uaa73\uaa74\uaa75\uaa76\uaa77\ua
 a78\uaa79\uaa7a\uaa7b\uaa7c\uaa7d\uaa7e\uaa7f\uaa80\uaa81\uaa82\uaa83\uaa84\uaa85\uaa86\uaa87\uaa88\uaa89\uaa8a\uaa8b\uaa8c\uaa8d\uaa8e\uaa8f\uaa90\uaa91\uaa92\uaa93\uaa94\uaa95\uaa96\uaa97\uaa98\uaa99\uaa9a\uaa9b\uaa9c\uaa9d\uaa9e\uaa9f\uaaa0\uaaa1\uaaa2\uaaa3\uaaa4\uaaa5\uaaa6\uaaa7\uaaa8\uaaa9\uaaaa\uaaab\uaaac\uaaad\uaaae\uaaaf\uaab0\uaab1\uaab2\uaab3\uaab4\uaab5\uaab6\uaab7\uaab8\uaab9\uaaba\uaabb\uaabc\uaabd\uaabe\uaabf\uaac0\uaac1\uaac2\uaac3\uaac4\uaac5\uaac6\uaac7\uaac8\uaac9\uaaca\uaacb\uaacc\uaacd\uaace\uaacf\uaad0\uaad1\uaad2\uaad3\uaad4\uaad5\uaad6\uaad7\uaad8\uaad9\uaada\uaadb\uaadc\uaadd\uaade\uaadf\uaae0\uaae1\uaae2\uaae3\uaae4\uaae5\uaae6\uaae7\uaae8\uaae9\uaaea\uaaeb\uaaec\uaaed\uaaee\uaaef\uaaf0\uaaf1\uaaf2\uaaf3\uaaf4\uaaf5\uaaf6\uaaf7\uaaf8\uaaf9\uaafa\uaafb\uaafc\uaafd\uaafe\uaaff\uab00\uab01\uab02\uab03\uab04\uab05\uab06\uab07\uab08\uab09\uab0a\uab0b\uab0c\uab0d\uab0e\uab0f\uab10\uab11\uab12\uab13\uab14\uab15\uab16\uab17\uab18\uab19\uab1a\uab1b\uab1c\uab1d\uab
 1e\uab1f\uab20\uab21\uab22\uab23\uab24\uab25\uab26\uab27\uab28\uab29\uab2a\uab2b\uab2c\uab2d\uab2e\uab2f\uab30\uab31\uab32\uab33\uab34\uab35\uab36\uab37\uab38\uab39\uab3a\uab3b\uab3c\uab3d\uab3e\uab3f\uab40\uab41\uab42\uab43\uab44\uab45\uab46\uab47\uab48\uab49\uab4a\uab4b\uab4c\uab4d\uab4e\uab4f\uab50\uab51\uab52\uab53\uab54\uab55\uab56\uab57\uab58\uab59\uab5a\uab5b\uab5c\uab5d\uab5e\uab5f\uab60\uab61\uab62\uab63\uab64\uab65\uab66\uab67\uab68\uab69\uab6a\uab6b\uab6c\uab6d\uab6e\uab6f\uab70\uab71\uab72\uab73\uab74\uab75\uab76\uab77\uab78\uab79\uab7a\uab7b\uab7c\uab7d\uab7e\uab7f\uab80\uab81\uab82\uab83\uab84\uab85\uab86\uab87\uab88\uab89\uab8a\uab8b\uab8c\uab8d\uab8e\uab8f\uab90\uab91\uab92\uab93\uab94\uab95\uab96\uab97\uab98\uab99\uab9a\uab9b\uab9c\uab9d\uab9e\uab9f\uaba0\uaba1\uaba2\uaba3\uaba4\uaba5\uaba6\uaba7\uaba8\uaba9\uabaa\uabab\uabac\uabad\uabae\uabaf\uabb0\uabb1\uabb2\uabb3\uabb4\uabb5\uabb6\uabb7\uabb8\uabb9\uabba\uabbb\uabbc\uabbd\uabbe\uabbf\uabc0\uabc1\uabc2\uabc3\uabc
 4\uabc5\uabc6\uabc7\uabc8\uabc9\uabca\uabcb\uabcc\uabcd\uabce\uabcf\uabd0\uabd1\uabd2\uabd3\uabd4\uabd5\uabd6\uabd7\uabd8\uabd9\uabda\uabdb\uabdc\uabdd\uabde\uabdf\uabe0\uabe1\uabe2\uabe3\uabe4\uabe5\uabe6\uabe7\uabe8\uabe9\uabea\uabeb\uabec\uabed\uabee\uabef\uabf0\uabf1\uabf2\uabf3\uabf4\uabf5\uabf6\uabf7\uabf8\uabf9\uabfa\uabfb\uabfc\uabfd\uabfe\uabff\ud7a4\ud7a5\ud7a6\ud7a7\ud7a8\ud7a9\ud7aa\ud7ab\ud7ac\ud7ad\ud7ae\ud7af\ud7b0\ud7b1\ud7b2\ud7b3\ud7b4\ud7b5\ud7b6\ud7b7\ud7b8\ud7b9\ud7ba\ud7bb\ud7bc\ud7bd\ud7be\ud7bf\ud7c0\ud7c1\ud7c2\ud7c3\ud7c4\ud7c5\ud7c6\ud7c7\ud7c8\ud7c9\ud7ca\ud7cb\ud7cc\ud7cd\ud7ce\ud7cf\ud7d0\ud7d1\ud7d2\ud7d3\ud7d4\ud7d5\ud7d6\ud7d7\ud7d8\ud7d9\ud7da\ud7db\ud7dc\ud7dd\ud7de\ud7df\ud7e0\ud7e1\ud7e2\ud7e3\ud7e4\ud7e5\ud7e6\ud7e7\ud7e8\ud7e9\ud7ea\ud7eb\ud7ec\ud7ed\ud7ee\ud7ef\ud7f0\ud7f1\ud7f2\ud7f3\ud7f4\ud7f5\ud7f6\ud7f7\ud7f8\ud7f9\ud7fa\ud7fb\ud7fc\ud7fd\ud7fe\ud7ff\ufa2e\ufa2f\ufa6b\ufa6c\ufa6d\ufa6e\ufa6f\ufada\ufadb\ufadc\ufadd\ufade\ufadf\ufae0\ufae1
 \ufae2\ufae3\ufae4\ufae5\ufae6\ufae7\ufae8\ufae9\ufaea\ufaeb\ufaec\ufaed\ufaee\ufaef\ufaf0\ufaf1\ufaf2\ufaf3\ufaf4\ufaf5\ufaf6\ufaf7\ufaf8\ufaf9\ufafa\ufafb\ufafc\ufafd\ufafe\ufaff\ufb07\ufb08\ufb09\ufb0a\ufb0b\ufb0c\ufb0d\ufb0e\ufb0f\ufb10\ufb11\ufb12\ufb18\ufb19\ufb1a\ufb1b\ufb1c\ufb37\ufb3d\ufb3f\ufb42\ufb45\ufbb2\ufbb3\ufbb4\ufbb5\ufbb6\ufbb7\ufbb8\ufbb9\ufbba\ufbbb\ufbbc\ufbbd\ufbbe\ufbbf\ufbc0\ufbc1\ufbc2\ufbc3\ufbc4\ufbc5\ufbc6\ufbc7\ufbc8\ufbc9\ufbca\ufbcb\ufbcc\ufbcd\ufbce\ufbcf\ufbd0\ufbd1\ufbd2\ufd40\ufd41\ufd42\ufd43\ufd44\ufd45\ufd46\ufd47\ufd48\ufd49\ufd4a\ufd4b\ufd4c\ufd4d\ufd4e\ufd4f\ufd90\ufd91\ufdc8\ufdc9\ufdca\ufdcb\ufdcc\ufdcd\ufdce\ufdcf\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea\ufdeb\ufdec\ufded\ufdee\ufdef\ufdfe\ufdff\ufe1a\ufe1b\ufe1c\ufe1d\ufe1e\ufe1f\ufe24\ufe25\ufe26\ufe27\ufe28\ufe29\ufe2a\ufe2b\ufe2c\ufe2d\ufe2e\ufe2f\ufe53\ufe67\ufe6c\
 ufe6d\ufe6e\ufe6f\ufe75\ufefd\ufefe\uff00\uffbf\uffc0\uffc1\uffc8\uffc9\uffd0\uffd1\uffd8\uffd9\uffdd\uffde\uffdf\uffe7\uffef\ufff0\ufff1\ufff2\ufff3\ufff4\ufff5\ufff6\ufff7\ufff8\ufffe'
-
-Co = u'\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009\ue00a\ue00b\ue00c\ue00d\ue00e\ue00f\ue010\ue011\ue012\ue013\ue014\ue015\ue016\ue017\ue018\ue019\ue01a\ue01b\ue01c\ue01d\ue01e\ue01f\ue020\ue021\ue022\ue023\ue024\ue025\ue026\ue027\ue028\ue029\ue02a\ue02b\ue02c\ue02d\ue02e\ue02f\ue030\ue031\ue032\ue033\ue034\ue035\ue036\ue037\ue038\ue039\ue03a\ue03b\ue03c\ue03d\ue03e\ue03f\ue040\ue041\ue042\ue043\ue044\ue045\ue046\ue047\ue048\ue049\ue04a\ue04b\ue04c\ue04d\ue04e\ue04f\ue050\ue051\ue052\ue053\ue054\ue055\ue056\ue057\ue058\ue059\ue05a\ue05b\ue05c\ue05d\ue05e\ue05f\ue060\ue061\ue062\ue063\ue064\ue065\ue066\ue067\ue068\ue069\ue06a\ue06b\ue06c\ue06d\ue06e\ue06f\ue070\ue071\ue072\ue073\ue074\ue075\ue076\ue077\ue078\ue079\ue07a\ue07b\ue07c\ue07d\ue07e\ue07f\ue080\ue081\ue082\ue083\ue084\ue085\ue086\ue087\ue088\ue089\ue08a\ue08b\ue08c\ue08d\ue08e\ue08f\ue090\ue091\ue092\ue093\ue094\ue095\ue096\ue097\ue098\ue099\ue09a\ue09b\ue09c\ue09d\ue09e\ue09f\ue0a0\ue0a1\ue0a2\ue0a3\ue0a4
 \ue0a5\ue0a6\ue0a7\ue0a8\ue0a9\ue0aa\ue0ab\ue0ac\ue0ad\ue0ae\ue0af\ue0b0\ue0b1\ue0b2\ue0b3\ue0b4\ue0b5\ue0b6\ue0b7\ue0b8\ue0b9\ue0ba\ue0bb\ue0bc\ue0bd\ue0be\ue0bf\ue0c0\ue0c1\ue0c2\ue0c3\ue0c4\ue0c5\ue0c6\ue0c7\ue0c8\ue0c9\ue0ca\ue0cb\ue0cc\ue0cd\ue0ce\ue0cf\ue0d0\ue0d1\ue0d2\ue0d3\ue0d4\ue0d5\ue0d6\ue0d7\ue0d8\ue0d9\ue0da\ue0db\ue0dc\ue0dd\ue0de\ue0df\ue0e0\ue0e1\ue0e2\ue0e3\ue0e4\ue0e5\ue0e6\ue0e7\ue0e8\ue0e9\ue0ea\ue0eb\ue0ec\ue0ed\ue0ee\ue0ef\ue0f0\ue0f1\ue0f2\ue0f3\ue0f4\ue0f5\ue0f6\ue0f7\ue0f8\ue0f9\ue0fa\ue0fb\ue0fc\ue0fd\ue0fe\ue0ff\ue100\ue101\ue102\ue103\ue104\ue105\ue106\ue107\ue108\ue109\ue10a\ue10b\ue10c\ue10d\ue10e\ue10f\ue110\ue111\ue112\ue113\ue114\ue115\ue116\ue117\ue118\ue119\ue11a\ue11b\ue11c\ue11d\ue11e\ue11f\ue120\ue121\ue122\ue123\ue124\ue125\ue126\ue127\ue128\ue129\ue12a\ue12b\ue12c\ue12d\ue12e\ue12f\ue130\ue131\ue132\ue133\ue134\ue135\ue136\ue137\ue138\ue139\ue13a\ue13b\ue13c\ue13d\ue13e\ue13f\ue140\ue141\ue142\ue143\ue144\ue145\ue146\ue147\ue148\ue149\ue14a\
 ue14b\ue14c\ue14d\ue14e\ue14f\ue150\ue151\ue152\ue153\ue154\ue155\ue156\ue157\ue158\ue159\ue15a\ue15b\ue15c\ue15d\ue15e\ue15f\ue160\ue161\ue162\ue163\ue164\ue165\ue166\ue167\ue168\ue169\ue16a\ue16b\ue16c\ue16d\ue16e\ue16f\ue170\ue171\ue172\ue173\ue174\ue175\ue176\ue177\ue178\ue179\ue17a\ue17b\ue17c\ue17d\ue17e\ue17f\ue180\ue181\ue182\ue183\ue184\ue185\ue186\ue187\ue188\ue189\ue18a\ue18b\ue18c\ue18d\ue18e\ue18f\ue190\ue191\ue192\ue193\ue194\ue195\ue196\ue197\ue198\ue199\ue19a\ue19b\ue19c\ue19d\ue19e\ue19f\ue1a0\ue1a1\ue1a2\ue1a3\ue1a4\ue1a5\ue1a6\ue1a7\ue1a8\ue1a9\ue1aa\ue1ab\ue1ac\ue1ad\ue1ae\ue1af\ue1b0\ue1b1\ue1b2\ue1b3\ue1b4\ue1b5\ue1b6\ue1b7\ue1b8\ue1b9\ue1ba\ue1bb\ue1bc\ue1bd\ue1be\ue1bf\ue1c0\ue1c1\ue1c2\ue1c3\ue1c4\ue1c5\ue1c6\ue1c7\ue1c8\ue1c9\ue1ca\ue1cb\ue1cc\ue1cd\ue1ce\ue1cf\ue1d0\ue1d1\ue1d2\ue1d3\ue1d4\ue1d5\ue1d6\ue1d7\ue1d8\ue1d9\ue1da\ue1db\ue1dc\ue1dd\ue1de\ue1df\ue1e0\ue1e1\ue1e2\ue1e3\ue1e4\ue1e5\ue1e6\ue1e7\ue1e8\ue1e9\ue1ea\ue1eb\ue1ec\ue1ed\ue1ee\ue1ef\ue1f0\u
 e1f1\ue1f2\ue1f3\ue1f4\ue1f5\ue1f6\ue1f7\ue1f8\ue1f9\ue1fa\ue1fb\ue1fc\ue1fd\ue1fe\ue1ff\ue200\ue201\ue202\ue203\ue204\ue205\ue206\ue207\ue208\ue209\ue20a\ue20b\ue20c\ue20d\ue20e\ue20f\ue210\ue211\ue212\ue213\ue214\ue215\ue216\ue217\ue218\ue219\ue21a\ue21b\ue21c\ue21d\ue21e\ue21f\ue220\ue221\ue222\ue223\ue224\ue225\ue226\ue227\ue228\ue229\ue22a\ue22b\ue22c\ue22d\ue22e\ue22f\ue230\ue231\ue232\ue233\ue234\ue235\ue236\ue237\ue238\ue239\ue23a\ue23b\ue23c\ue23d\ue23e\ue23f\ue240\ue241\ue242\ue243\ue244\ue245\ue246\ue247\ue248\ue249\ue24a\ue24b\ue24c\ue24d\ue24e\ue24f\ue250\ue251\ue252\ue253\ue254\ue255\ue256\ue257\ue258\ue259\ue25a\ue25b\ue25c\ue25d\ue25e\ue25f\ue260\ue261\ue262\ue263\ue264\ue265\ue266\ue267\ue268\ue269\ue26a\ue26b\ue26c\ue26d\ue26e\ue26f\ue270\ue271\ue272\ue273\ue274\ue275\ue276\ue277\ue278\ue279\ue27a\ue27b\ue27c\ue27d\ue27e\ue27f\ue280\ue281\ue282\ue283\ue284\ue285\ue286\ue287\ue288\ue289\ue28a\ue28b\ue28c\ue28d\ue28e\ue28f\ue290\ue291\ue292\ue293\ue294\ue295\ue296\ue
 297\ue298\ue299\ue29a\ue29b\ue29c\ue29d\ue29e\ue29f\ue2a0\ue2a1\ue2a2\ue2a3\ue2a4\ue2a5\ue2a6\ue2a7\ue2a8\ue2a9\ue2aa\ue2ab\ue2ac\ue2ad\ue2ae\ue2af\ue2b0\ue2b1\ue2b2\ue2b3\ue2b4\ue2b5\ue2b6\ue2b7\ue2b8\ue2b9\ue2ba\ue2bb\ue2bc\ue2bd\ue2be\ue2bf\ue2c0\ue2c1\ue2c2\ue2c3\ue2c4\ue2c5\ue2c6\ue2c7\ue2c8\ue2c9\ue2ca\ue2cb\ue2cc\ue2cd\ue2ce\ue2cf\ue2d0\ue2d1\ue2d2\ue2d3\ue2d4\ue2d5\ue2d6\ue2d7\ue2d8\ue2d9\ue2da\ue2db\ue2dc\ue2dd\ue2de\ue2df\ue2e0\ue2e1\ue2e2\ue2e3\ue2e4\ue2e5\ue2e6\ue2e7\ue2e8\ue2e9\ue2ea\ue2eb\ue2ec\ue2ed\ue2ee\ue2ef\ue2f0\ue2f1\ue2f2\ue2f3\ue2f4\ue2f5\ue2f6\ue2f7\ue2f8\ue2f9\ue2fa\ue2fb\ue2fc\ue2fd\ue2fe\ue2ff\ue300\ue301\ue302\ue303\ue304\ue305\ue306\ue307\ue308\ue309\ue30a\ue30b\ue30c\ue30d\ue30e\ue30f\ue310\ue311\ue312\ue313\ue314\ue315\ue316\ue317\ue318\ue319\ue31a\ue31b\ue31c\ue31d\ue31e\ue31f\ue320\ue321\ue322\ue323\ue324\ue325\ue326\ue327\ue328\ue329\ue32a\ue32b\ue32c\ue32d\ue32e\ue32f\ue330\ue331\ue332\ue333\ue334\ue335\ue336\ue337\ue338\ue339\ue33a\ue33b\ue33c\ue3
 3d\ue33e\ue33f\ue340\ue341\ue342\ue343\ue344\ue345\ue346\ue347\ue348\ue349\ue34a\ue34b\ue34c\ue34d\ue34e\ue34f\ue350\ue351\ue352\ue353\ue354\ue355\ue356\ue357\ue358\ue359\ue35a\ue35b\ue35c\ue35d\ue35e\ue35f\ue360\ue361\ue362\ue363\ue364\ue365\ue366\ue367\ue368\ue369\ue36a\ue36b\ue36c\ue36d\ue36e\ue36f\ue370\ue371\ue372\ue373\ue374\ue375\ue376\ue377\ue378\ue379\ue37a\ue37b\ue37c\ue37d\ue37e\ue37f\ue380\ue381\ue382\ue383\ue384\ue385\ue386\ue387\ue388\ue389\ue38a\ue38b\ue38c\ue38d\ue38e\ue38f\ue390\ue391\ue392\ue393\ue394\ue395\ue396\ue397\ue398\ue399\ue39a\ue39b\ue39c\ue39d\ue39e\ue39f\ue3a0\ue3a1\ue3a2\ue3a3\ue3a4\ue3a5\ue3a6\ue3a7\ue3a8\ue3a9\ue3aa\ue3ab\ue3ac\ue3ad\ue3ae\ue3af\ue3b0\ue3b1\ue3b2\ue3b3\ue3b4\ue3b5\ue3b6\ue3b7\ue3b8\ue3b9\ue3ba\ue3bb\ue3bc\ue3bd\ue3be\ue3bf\ue3c0\ue3c1\ue3c2\ue3c3\ue3c4\ue3c5\ue3c6\ue3c7\ue3c8\ue3c9\ue3ca\ue3cb\ue3cc\ue3cd\ue3ce\ue3cf\ue3d0\ue3d1\ue3d2\ue3d3\ue3d4\ue3d5\ue3d6\ue3d7\ue3d8\ue3d9\ue3da\ue3db\ue3dc\ue3dd\ue3de\ue3df\ue3e0\ue3e1\ue3e2\ue3e
 3\ue3e4\ue3e5\ue3e6\ue3e7\ue3e8\ue3e9\ue3ea\ue3eb\ue3ec\ue3ed\ue3ee\ue3ef\ue3f0\ue3f1\ue3f2\ue3f3\ue3f4\ue3f5\ue3f6\ue3f7\ue3f8\ue3f9\ue3fa\ue3fb\ue3fc\ue3fd\ue3fe\ue3ff\ue400\ue401\ue402\ue403\ue404\ue405\ue406\ue407\ue408\ue409\ue40a\ue40b\ue40c\ue40d\ue40e\ue40f\ue410\ue411\ue412\ue413\ue414\ue415\ue416\ue417\ue418\ue419\ue41a\ue41b\ue41c\ue41d\ue41e\ue41f\ue420\ue421\ue422\ue423\ue424\ue425\ue426\ue427\ue428\ue429\ue42a\ue42b\ue42c\ue42d\ue42e\ue42f\ue430\ue431\ue432\ue433\ue434\ue435\ue436\ue437\ue438\ue439\ue43a\ue43b\ue43c\ue43d\ue43e\ue43f\ue440\ue441\ue442\ue443\ue444\ue445\ue446\ue447\ue448\ue449\ue44a\ue44b\ue44c\ue44d\ue44e\ue44f\ue450\ue451\ue452\ue453\ue454\ue455\ue456\ue457\ue458\ue459\ue45a\ue45b\ue45c\ue45d\ue45e\ue45f\ue460\ue461\ue462\ue463\ue464\ue465\ue466\ue467\ue468\ue469\ue46a\ue46b\ue46c\ue46d\ue46e\ue46f\ue470\ue471\ue472\ue473\ue474\ue475\ue476\ue477\ue478\ue479\ue47a\ue47b\ue47c\ue47d\ue47e\ue47f\ue480\ue481\ue482\ue483\ue484\ue485\ue486\ue487\ue488\ue489
 \ue48a\ue48b\ue48c\ue48d\ue48e\ue48f\ue490\ue491\ue492\ue493\ue494\ue495\ue496\ue497\ue498\ue499\ue49a\ue49b\ue49c\ue49d\ue49e\ue49f\ue4a0\ue4a1\ue4a2\ue4a3\ue4a4\ue4a5\ue4a6\ue4a7\ue4a8\ue4a9\ue4aa\ue4ab\ue4ac\ue4ad\ue4ae\ue4af\ue4b0\ue4b1\ue4b2\ue4b3\ue4b4\ue4b5\ue4b6\ue4b7\ue4b8\ue4b9\ue4ba\ue4bb\ue4bc\ue4bd\ue4be\ue4bf\ue4c0\ue4c1\ue4c2\ue4c3\ue4c4\ue4c5\ue4c6\ue4c7\ue4c8\ue4c9\ue4ca\ue4cb\ue4cc\ue4cd\ue4ce\ue4cf\ue4d0\ue4d1\ue4d2\ue4d3\ue4d4\ue4d5\ue4d6\ue4d7\ue4d8\ue4d9\ue4da\ue4db\ue4dc\ue4dd\ue4de\ue4df\ue4e0\ue4e1\ue4e2\ue4e3\ue4e4\ue4e5\ue4e6\ue4e7\ue4e8\ue4e9\ue4ea\ue4eb\ue4ec\ue4ed\ue4ee\ue4ef\ue4f0\ue4f1\ue4f2\ue4f3\ue4f4\ue4f5\ue4f6\ue4f7\ue4f8\ue4f9\ue4fa\ue4fb\ue4fc\ue4fd\ue4fe\ue4ff\ue500\ue501\ue502\ue503\ue504\ue505\ue506\ue507\ue508\ue509\ue50a\ue50b\ue50c\ue50d\ue50e\ue50f\ue510\ue511\ue512\ue513\ue514\ue515\ue516\ue517\ue518\ue519\ue51a\ue51b\ue51c\ue51d\ue51e\ue51f\ue520\ue521\ue522\ue523\ue524\ue525\ue526\ue527\ue528\ue529\ue52a\ue52b\ue52c\ue52d\ue52e\ue52f\
 ue530\ue531\ue532\ue533\ue534\ue535\ue536\ue537\ue538\ue539\ue53a\ue53b\ue53c\ue53d\ue53e\ue53f\ue540\ue541\ue542\ue543\ue544\ue545\ue546\ue547\ue548\ue549\ue54a\ue54b\ue54c\ue54d\ue54e\ue54f\ue550\ue551\ue552\ue553\ue554\ue555\ue556\ue557\ue558\ue559\ue55a\ue55b\ue55c\ue55d\ue55e\ue55f\ue560\ue561\ue562\ue563\ue564\ue565\ue566\ue567\ue568\ue569\ue56a\ue56b\ue56c\ue56d\ue56e\ue56f\ue570\ue571\ue572\ue573\ue574\ue575\ue576\ue577\ue578\ue579\ue57a\ue57b\ue57c\ue57d\ue57e\ue57f\ue580\ue581\ue582\ue583\ue584\ue585\ue586\ue587\ue588\ue589\ue58a\ue58b\ue58c\ue58d\ue58e\ue58f\ue590\ue591\ue592\ue593\ue594\ue595\ue596\ue597\ue598\ue599\ue59a\ue59b\ue59c\ue59d\ue59e\ue59f\ue5a0\ue5a1\ue5a2\ue5a3\ue5a4\ue5a5\ue5a6\ue5a7\ue5a8\ue5a9\ue5aa\ue5ab\ue5ac\ue5ad\ue5ae\ue5af\ue5b0\ue5b1\ue5b2\ue5b3\ue5b4\ue5b5\ue5b6\ue5b7\ue5b8\ue5b9\ue5ba\ue5bb\ue5bc\ue5bd\ue5be\ue5bf\ue5c0\ue5c1\ue5c2\ue5c3\ue5c4\ue5c5\ue5c6\ue5c7\ue5c8\ue5c9\ue5ca\ue5cb\ue5cc\ue5cd\ue5ce\ue5cf\ue5d0\ue5d1\ue5d2\ue5d3\ue5d4\ue5d5\u
 e5d6\ue5d7\ue5d8\ue5d9\ue5da\ue5db\ue5dc\ue5dd\ue5de\ue5df\ue5e0\ue5e1\ue5e2\ue5e3\ue5e4\ue5e5\ue5e6\ue5e7\ue5e8\ue5e9\ue5ea\ue5eb\ue5ec\ue5ed\ue5ee\ue5ef\ue5f0\ue5f1\ue5f2\ue5f3\ue5f4\ue5f5\ue5f6\ue5f7\ue5f8\ue5f9\ue5fa\ue5fb\ue5fc\ue5fd\ue5fe\ue5ff\ue600\ue601\ue602\ue603\ue604\ue605\ue606\ue607\ue608\ue609\ue60a\ue60b\ue60c\ue60d\ue60e\ue60f\ue610\ue611\ue612\ue613\ue614\ue615\ue616\ue617\ue618\ue619\ue61a\ue61b\ue61c\ue61d\ue61e\ue61f\ue620\ue621\ue622\ue623\ue624\ue625\ue626\ue627\ue628\ue629\ue62a\ue62b\ue62c\ue62d\ue62e\ue62f\ue630\ue631\ue632\ue633\ue634\ue635\ue636\ue637\ue638\ue639\ue63a\ue63b\ue63c\ue63d\ue63e\ue63f\ue640\ue641\ue642\ue643\ue644\ue645\ue646\ue647\ue648\ue649\ue64a\ue64b\ue64c\ue64d\ue64e\ue64f\ue650\ue651\ue652\ue653\ue654\ue655\ue656\ue657\ue658\ue659\ue65a\ue65b\ue65c\ue65d\ue65e\ue65f\ue660\ue661\ue662\ue663\ue664\ue665\ue666\ue667\ue668\ue669\ue66a\ue66b\ue66c\ue66d\ue66e\ue66f\ue670\ue671\ue672\ue673\ue674\ue675\ue676\ue677\ue678\ue679\ue67a\ue67b\ue
 67c\ue67d\ue67e\ue67f\ue680\ue681\ue682\ue683\ue684\ue685\ue686\ue687\ue688\ue689\ue68a\ue68b\ue68c\ue68d\ue68e\ue68f\ue690\ue691\ue692\ue693\ue694\ue695\ue696\ue697\ue698\ue699\ue69a\ue69b\ue69c\ue69d\ue69e\ue69f\ue6a0\ue6a1\ue6a2\ue6a3\ue6a4\ue6a5\ue6a6\ue6a7\ue6a8\ue6a9\ue6aa\ue6ab\ue6ac\ue6ad\ue6ae\ue6af\ue6b0\ue6b1\ue6b2\ue6b3\ue6b4\ue6b5\ue6b6\ue6b7\ue6b8\ue6b9\ue6ba\ue6bb\ue6bc\ue6bd\ue6be\ue6bf\ue6c0\ue6c1\ue6c2\ue6c3\ue6c4\ue6c5\ue6c6\ue6c7\ue6c8\ue6c9\ue6ca\ue6cb\ue6cc\ue6cd\ue6ce\ue6cf\ue6d0\ue6d1\ue6d2\ue6d3\ue6d4\ue6d5\ue6d6\ue6d7\ue6d8\ue6d9\ue6da\ue6db\ue6dc\ue6dd\ue6de\ue6df\ue6e0\ue6e1\ue6e2\ue6e3\ue6e4\ue6e5\ue6e6\ue6e7\ue6e8\ue6e9\ue6ea\ue6eb\ue6ec\ue6ed\ue6ee\ue6ef\ue6f0\ue6f1\ue6f2\ue6f3\ue6f4\ue6f5\ue6f6\ue6f7\ue6f8\ue6f9\ue6fa\ue6fb\ue6fc\ue6fd\ue6fe\ue6ff\ue700\ue701\ue702\ue703\ue704\ue705\ue706\ue707\ue708\ue709\ue70a\ue70b\ue70c\ue70d\ue70e\ue70f\ue710\ue711\ue712\ue713\ue714\ue715\ue716\ue717\ue718\ue719\ue71a\ue71b\ue71c\ue71d\ue71e\ue71f\ue720\ue721\ue7
 22\ue723\ue724\ue725\ue726\ue727\ue728\ue729\ue72a\ue72b\ue72c\ue72d\ue72e\ue72f\ue730\ue731\ue732\ue733\ue734\ue735\ue736\ue737\ue738\ue739\ue73a\ue73b\ue73c\ue73d\ue73e\ue73f\ue740\ue741\ue742\ue743\ue744\ue745\ue746\ue747\ue748\ue749\ue74a\ue74b\ue74c\ue74d\ue74e\ue74f\ue750\ue751\ue752\ue753\ue754\ue755\ue756\ue757\ue758\ue759\ue75a\ue75b\ue75c\ue75d\ue75e\ue75f\ue760\ue761\ue762\ue763\ue764\ue765\ue766\ue767\ue768\ue769\ue76a\ue76b\ue76c\ue76d\ue76e\ue76f\ue770\ue771\ue772\ue773\ue774\ue775\ue776\ue777\ue778\ue779\ue77a\ue77b\ue77c\ue77d\ue77e\ue77f\ue780\ue781\ue782\ue783\ue784\ue785\ue786\ue787\ue788\ue789\ue78a\ue78b\ue78c\ue78d\ue78e\ue78f\ue790\ue791\ue792\ue793\ue794\ue795\ue796\ue797\ue798\ue799\ue79a\ue79b\ue79c\ue79d\ue79e\ue79f\ue7a0\ue7a1\ue7a2\ue7a3\ue7a4\ue7a5\ue7a6\ue7a7\ue7a8\ue7a9\ue7aa\ue7ab\ue7ac\ue7ad\ue7ae\ue7af\ue7b0\ue7b1\ue7b2\ue7b3\ue7b4\ue7b5\ue7b6\ue7b7\ue7b8\ue7b9\ue7ba\ue7bb\ue7bc\ue7bd\ue7be\ue7bf\ue7c0\ue7c1\ue7c2\ue7c3\ue7c4\ue7c5\ue7c6\ue7c7\ue7c
 8\ue7c9\ue7ca\ue7cb\ue7cc\ue7cd\ue7ce\ue7cf\ue7d0\ue7d1\ue7d2\ue7d3\ue7d4\ue7d5\ue7d6\ue7d7\ue7d8\ue7d9\ue7da\ue7db\ue7dc\ue7dd\ue7de\ue7df\ue7e0\ue7e1\ue7e2\ue7e3\ue7e4\ue7e5\ue7e6\ue7e7\ue7e8\ue7e9\ue7ea\ue7eb\ue7ec\ue7ed\ue7ee\ue7ef\ue7f0\ue7f1\ue7f2\ue7f3\ue7f4\ue7f5\ue7f6\ue7f7\ue7f8\ue7f9\ue7fa\ue7fb\ue7fc\ue7fd\ue7fe\ue7ff\ue800\ue801\ue802\ue803\ue804\ue805\ue806\ue807\ue808\ue809\ue80a\ue80b\ue80c\ue80d\ue80e\ue80f\ue810\ue811\ue812\ue813\ue814\ue815\ue816\ue817\ue818\ue819\ue81a\ue81b\ue81c\ue81d\ue81e\ue81f\ue820\ue821\ue822\ue823\ue824\ue825\ue826\ue827\ue828\ue829\ue82a\ue82b\ue82c\ue82d\ue82e\ue82f\ue830\ue831\ue832\ue833\ue834\ue835\ue836\ue837\ue838\ue839\ue83a\ue83b\ue83c\ue83d\ue83e\ue83f\ue840\ue841\ue842\ue843\ue844\ue845\ue846\ue847\ue848\ue849\ue84a\ue84b\ue84c\ue84d\ue84e\ue84f\ue850\ue851\ue852\ue853\ue854\ue855\ue856\ue857\ue858\ue859\ue85a\ue85b\ue85c\ue85d\ue85e\ue85f\ue860\ue861\ue862\ue863\ue864\ue865\ue866\ue867\ue868\ue869\ue86a\ue86b\ue86c\ue86d\ue86e
 \ue86f\ue870\ue871\ue872\ue873\ue874\ue875\ue876\ue877\ue878\ue879\ue87a\ue87b\ue87c\ue87d\ue87e\ue87f\ue880\ue881\ue882\ue883\ue884\ue885\ue886\ue887\ue888\ue889\ue88a\ue88b\ue88c\ue88d\ue88e\ue88f\ue890\ue891\ue892\ue893\ue894\ue895\ue896\ue897\ue898\ue899\ue89a\ue89b\ue89c\ue89d\ue89e\ue89f\ue8a0\ue8a1\ue8a2\ue8a3\ue8a4\ue8a5\ue8a6\ue8a7\ue8a8\ue8a9\ue8aa\ue8ab\ue8ac\ue8ad\ue8ae\ue8af\ue8b0\ue8b1\ue8b2\ue8b3\ue8b4\ue8b5\ue8b6\ue8b7\ue8b8\ue8b9\ue8ba\ue8bb\ue8bc\ue8bd\ue8be\ue8bf\ue8c0\ue8c1\ue8c2\ue8c3\ue8c4\ue8c5\ue8c6\ue8c7\ue8c8\ue8c9\ue8ca\ue8cb\ue8cc\ue8cd\ue8ce\ue8cf\ue8d0\ue8d1\ue8d2\ue8d3\ue8d4\ue8d5\ue8d6\ue8d7\ue8d8\ue8d9\ue8da\ue8db\ue8dc\ue8dd\ue8de\ue8df\ue8e0\ue8e1\ue8e2\ue8e3\ue8e4\ue8e5\ue8e6\ue8e7\ue8e8\ue8e9\ue8ea\ue8eb\ue8ec\ue8ed\ue8ee\ue8ef\ue8f0\ue8f1\ue8f2\ue8f3\ue8f4\ue8f5\ue8f6\ue8f7\ue8f8\ue8f9\ue8fa\ue8fb\ue8fc\ue8fd\ue8fe\ue8ff\ue900\ue901\ue902\ue903\ue904\ue905\ue906\ue907\ue908\ue909\ue90a\ue90b\ue90c\ue90d\ue90e\ue90f\ue910\ue911\ue912\ue913\ue914\
 ue915\ue916\ue917\ue918\ue919\ue91a\ue91b\ue91c\ue91d\ue91e\ue91f\ue920\ue921\ue922\ue923\ue924\ue925\ue926\ue927\ue928\ue929\ue92a\ue92b\ue92c\ue92d\ue92e\ue92f\ue930\ue931\ue932\ue933\ue934\ue935\ue936\ue937\ue938\ue939\ue93a\ue93b\ue93c\ue93d\ue93e\ue93f\ue940\ue941\ue942\ue943\ue944\ue945\ue946\ue947\ue948\ue949\ue94a\ue94b\ue94c\ue94d\ue94e\ue94f\ue950\ue951\ue952\ue953\ue954\ue955\ue956\ue957\ue958\ue959\ue95a\ue95b\ue95c\ue95d\ue95e\ue95f\ue960\ue961\ue962\ue963\ue964\ue965\ue966\ue967\ue968\ue969\ue96a\ue96b\ue96c\ue96d\ue96e\ue96f\ue970\ue971\ue972\ue973\ue974\ue975\ue976\ue977\ue978\ue979\ue97a\ue97b\ue97c\ue97d\ue97e\ue97f\ue980\ue981\ue982\ue983\ue984\ue985\ue986\ue987\ue988\ue989\ue98a\ue98b\ue98c\ue98d\ue98e\ue98f\ue990\ue991\ue992\ue993\ue994\ue995\ue996\ue997\ue998\ue999\ue99a\ue99b\ue99c\ue99d\ue99e\ue99f\ue9a0\ue9a1\ue9a2\ue9a3\ue9a4\ue9a5\ue9a6\ue9a7\ue9a8\ue9a9\ue9aa\ue9ab\ue9ac\ue9ad\ue9ae\ue9af\ue9b0\ue9b1\ue9b2\ue9b3\ue9b4\ue9b5\ue9b6\ue9b7\ue9b8\ue9b9\ue9ba\u
 e9bb\ue9bc\ue9bd\ue9be\ue9bf\ue9c0\ue9c1\ue9c2\ue9c3\ue9c4\ue9c5\ue9c6\ue9c7\ue9c8\ue9c9\ue9ca\ue9cb\ue9cc\ue9cd\ue9ce\ue9cf\ue9d0\ue9d1\ue9d2\ue9d3\ue9d4\ue9d5\ue9d6\ue9d7\ue9d8\ue9d9\ue9da\ue9db\ue9dc\ue9dd\ue9de\ue9df\ue9e0\ue9e1\ue9e2\ue9e3\ue9e4\ue9e5\ue9e6\ue9e7\ue9e8\ue9e9\ue9ea\ue9eb\ue9ec\ue9ed\ue9ee\ue9ef\ue9f0\ue9f1\ue9f2\ue9f3\ue9f4\ue9f5\ue9f6\ue9f7\ue9f8\ue9f9\ue9fa\ue9fb\ue9fc\ue9fd\ue9fe\ue9ff\uea00\uea01\uea02\uea03\uea04\uea05\uea06\uea07\uea08\uea09\uea0a\uea0b\uea0c\uea0d\uea0e\uea0f\uea10\uea11\uea12\uea13\uea14\uea15\uea16\uea17\uea18\uea19\uea1a\uea1b\uea1c\uea1d\uea1e\uea1f\uea20\uea21\uea22\uea23\uea24\uea25\uea26\uea27\uea28\uea29\uea2a\uea2b\uea2c\uea2d\uea2e\uea2f\uea30\uea31\uea32\uea33\uea34\uea35\uea36\uea37\uea38\uea39\uea3a\uea3b\uea3c\uea3d\uea3e\uea3f\uea40\uea41\uea42\uea43\uea44\uea45\uea46\uea47\uea48\uea49\uea4a\uea4b\uea4c\uea4d\uea4e\uea4f\uea50\uea51\uea52\uea53\uea54\uea55\uea56\uea57\uea58\uea59\uea5a\uea5b\uea5c\uea5d\uea5e\uea5f\uea60\ue
 a61\uea62\uea63\uea64\uea65\uea66\uea67\uea68\uea69\uea6a\uea6b\uea6c\uea6d\uea6e\uea6f\uea70\uea71\uea72\uea73\uea74\uea75\uea76\uea77\uea78\uea79\uea7a\uea7b\uea7c\uea7d\uea7e\uea7f\uea80\uea81\uea82\uea83\uea84\uea85\uea86\uea87\uea88\uea89\uea8a\uea8b\uea8c\uea8d\uea8e\uea8f\uea90\uea91\uea92\uea93\uea94\uea95\uea96\uea97\uea98\uea99\uea9a\uea9b\uea9c\uea9d\uea9e\uea9f\ueaa0\ueaa1\ueaa2\ueaa3\ueaa4\ueaa5\ueaa6\ueaa7\ueaa8\ueaa9\ueaaa\ueaab\ueaac\ueaad\ueaae\ueaaf\ueab0\ueab1\ueab2\ueab3\ueab4\ueab5\ueab6\ueab7\ueab8\ueab9\ueaba\ueabb\ueabc\ueabd\ueabe\ueabf\ueac0\ueac1\ueac2\ueac3\ueac4\ueac5\ueac6\ueac7\ueac8\ueac9\ueaca\ueacb\ueacc\ueacd\ueace\ueacf\uead0\uead1\uead2\uead3\uead4\uead5\uead6\uead7\uead8\uead9\ueada\ueadb\ueadc\ueadd\ueade\ueadf\ueae0\ueae1\ueae2\ueae3\ueae4\ueae5\ueae6\ueae7\ueae8\ueae9\ueaea\ueaeb\ueaec\ueaed\ueaee\ueaef\ueaf0\ueaf1\ueaf2\ueaf3\ueaf4\ueaf5\ueaf6\ueaf7\ueaf8\ueaf9\ueafa\ueafb\ueafc\ueafd\ueafe\ueaff\ueb00\ueb01\ueb02\ueb03\ueb04\ueb05\ueb06\ueb
 07\ueb08\ueb09\ueb0a\ueb0b\ueb0c\ueb0d\ueb0e\ueb0f\ueb10\ueb11\ueb12\ueb13\ueb14\ueb15\ueb16\ueb17\ueb18\ueb19\ueb1a\ueb1b\ueb1c\ueb1d\ueb1e\ueb1f\ueb20\ueb21\ueb22\ueb23\ueb24\ueb25\ueb26\ueb27\ueb28\ueb29\ueb2a\ueb2b\ueb2c\ueb2d\ueb2e\ueb2f\ueb30\ueb31\ueb32\ueb33\ueb34\ueb35\ueb36\ueb37\ueb38\ueb39\ueb3a\ueb3b\ueb3c\ueb3d\ueb3e\ueb3f\ueb40\ueb41\ueb42\ueb43\ueb44\ueb45\ueb46\ueb47\ueb48\ueb49\ueb4a\ueb4b\ueb4c\ueb4d\ueb4e\ueb4f\ueb50\ueb51\ueb52\ueb53\ueb54\ueb55\ueb56\ueb57\ueb58\ueb59\ueb5a\ueb5b\ueb5c\ueb5d\ueb5e\ueb5f\ueb60\ueb61\ueb62\ueb63\ueb64\ueb65\ueb66\ueb67\ueb68\ueb69\ueb6a\ueb6b\ueb6c\ueb6d\ueb6e\ueb6f\ueb70\ueb71\ueb72\ueb73\ueb74\ueb75\ueb76\ueb77\ueb78\ueb79\ueb7a\ueb7b\ueb7c\ueb7d\ueb7e\ueb7f\ueb80\ueb81\ueb82\ueb83\ueb84\ueb85\ueb86\ueb87\ueb88\ueb89\ueb8a\ueb8b\ueb8c\ueb8d\ueb8e\ueb8f\ueb90\ueb91\ueb92\ueb93\ueb94\ueb95\ueb96\ueb97\ueb98\ueb99\ueb9a\ueb9b\ueb9c\ueb9d\ueb9e\ueb9f\ueba0\ueba1\ueba2\ueba3\ueba4\ueba5\ueba6\ueba7\ueba8\ueba9\uebaa\uebab\uebac\ueba
 d\uebae\uebaf\uebb0\uebb1\uebb2\uebb3\uebb4\uebb5\uebb6\uebb7\uebb8\uebb9\uebba\uebbb\uebbc\uebbd\uebbe\uebbf\uebc0\uebc1\uebc2\uebc3\uebc4\uebc5\uebc6\uebc7\uebc8\uebc9\uebca\uebcb\uebcc\uebcd\uebce\uebcf\uebd0\uebd1\uebd2\uebd3\uebd4\uebd5\uebd6\uebd7\uebd8\uebd9\uebda\uebdb\uebdc\uebdd\uebde\uebdf\uebe0\uebe1\uebe2\uebe3\uebe4\uebe5\uebe6\uebe7\uebe8\uebe9\uebea\uebeb\uebec\uebed\uebee\uebef\uebf0\uebf1\uebf2\uebf3\uebf4\uebf5\uebf6\uebf7\uebf8\uebf9\uebfa\uebfb\uebfc\uebfd\uebfe\uebff\uec00\uec01\uec02\uec03\uec04\uec05\uec06\uec07\uec08\uec09\uec0a\uec0b\uec0c\uec0d\uec0e\uec0f\uec10\uec11\uec12\uec13\uec14\uec15\uec16\uec17\uec18\uec19\uec1a\uec1b\uec1c\uec1d\uec1e\uec1f\uec20\uec21\uec22\uec23\uec24\uec25\uec26\uec27\uec28\uec29\uec2a\uec2b\uec2c\uec2d\uec2e\uec2f\uec30\uec31\uec32\uec33\uec34\uec35\uec36\uec37\uec38\uec39\uec3a\uec3b\uec3c\uec3d\uec3e\uec3f\uec40\uec41\uec42\uec43\uec44\uec45\uec46\uec47\uec48\uec49\uec4a\uec4b\uec4c\uec4d\uec4e\uec4f\uec50\uec51\uec52\uec53
 \uec54\uec55\uec56\uec57\uec58\uec59\uec5a\uec5b\uec5c\uec5d\uec5e\uec5f\uec60\uec61\uec62\uec63\uec64\uec65\uec66\uec67\uec68\uec69\uec6a\uec6b\uec6c\uec6d\uec6e\uec6f\uec70\uec71\uec72\uec73\uec74\uec75\uec76\uec77\uec78\uec79\uec7a\uec7b\uec7c\uec7d\uec7e\uec7f\uec80\uec81\uec82\uec83\uec84\uec85\uec86\uec87\uec88\uec89\uec8a\uec8b\uec8c\uec8d\uec8e\uec8f\uec90\uec91\uec92\uec93\uec94\uec95\uec96\uec97\uec98\uec99\uec9a\uec9b\uec9c\uec9d\uec9e\uec9f\ueca0\ueca1\ueca2\ueca3\ueca4\ueca5\ueca6\ueca7\ueca8\ueca9\uecaa\uecab\uecac\uecad\uecae\uecaf\uecb0\uecb1\uecb2\uecb3\uecb4\uecb5\uecb6\uecb7\uecb8\uecb9\uecba\uecbb\uecbc\uecbd\uecbe\uecbf\uecc0\uecc1\uecc2\uecc3\uecc4\uecc5\uecc6\uecc7\uecc8\uecc9\uecca\ueccb\ueccc\ueccd\uecce\ueccf\uecd0\uecd1\uecd2\uecd3\uecd4\uecd5\uecd6\uecd7\uecd8\uecd9\uecda\uecdb\uecdc\uecdd\uecde\uecdf\uece0\uece1\uece2\uece3\uece4\uece5\uece6\uece7\uece8\uece9\uecea\ueceb\uecec\ueced\uecee\uecef\uecf0\uecf1\uecf2\uecf3\uecf4\uecf5\uecf6\uecf7\uecf8\uecf9\
 uecfa\uecfb\uecfc\uecfd\uecfe\uecff\ued00\ued01\ued02\ued03\ued04\ued05\ued06\ued07\ued08\ued09\ued0a\ued0b\ued0c\ued0d\ued0e\ued0f\ued10\ued11\ued12\ued13\ued14\ued15\ued16\ued17\ued18\ued19\ued1a\ued1b\ued1c\ued1d\ued1e\ued1f\ued20\ued21\ued22\ued23\ued24\ued25\ued26\ued27\ued28\ued29\ued2a\ued2b\ued2c\ued2d\ued2e\ued2f\ued30\ued31\ued32\ued33\ued34\ued35\ued36\ued37\ued38\ued39\ued3a\ued3b\ued3c\ued3d\ued3e\ued3f\ued40\ued41\ued42\ued43\ued44\ued45\ued46\ued47\ued48\ued49\ued4a\ued4b\ued4c\ued4d\ued4e\ued4f\ued50\ued51\ued52\ued53\ued54\ued55\ued56\ued57\ued58\ued59\ued5a\ued5b\ued5c\ued5d\ued5e\ued5f\ued60\ued61\ued62\ued63\ued64\ued65\ued66\ued67\ued68\ued69\ued6a\ued6b\ued6c\ued6d\ued6e\ued6f\ued70\ued71\ued72\ued73\ued74\ued75\ued76\ued77\ued78\ued79\ued7a\ued7b\ued7c\ued7d\ued7e\ued7f\ued80\ued81\ued82\ued83\ued84\ued85\ued86\ued87\ued88\ued89\ued8a\ued8b\ued8c\ued8d\ued8e\ued8f\ued90\ued91\ued92\ued93\ued94\ued95\ued96\ued97\ued98\ued99\ued9a\ued9b\ued9c\ued9d\ued9e\ued9f\u
 eda0\ueda1\ueda2\ueda3\ueda4\ueda5\ueda6\ueda7\ueda8\ueda9\uedaa\uedab\uedac\uedad\uedae\uedaf\uedb0\uedb1\uedb2\uedb3\uedb4\uedb5\uedb6\uedb7\uedb8\uedb9\uedba\uedbb\uedbc\uedbd\uedbe\uedbf\uedc0\uedc1\uedc2\uedc3\uedc4\uedc5\uedc6\uedc7\uedc8\uedc9\uedca\uedcb\uedcc\uedcd\uedce\uedcf\uedd0\uedd1\uedd2\uedd3\uedd4\uedd5\uedd6\uedd7\uedd8\uedd9\uedda\ueddb\ueddc\ueddd\uedde\ueddf\uede0\uede1\uede2\uede3\uede4\uede5\uede6\uede7\uede8\uede9\uedea\uedeb\uedec\ueded\uedee\uedef\uedf0\uedf1\uedf2\uedf3\uedf4\uedf5\uedf6\uedf7\uedf8\uedf9\uedfa\uedfb\uedfc\uedfd\uedfe\uedff\uee00\uee01\uee02\uee03\uee04\uee05\uee06\uee07\uee08\uee09\uee0a\uee0b\uee0c\uee0d\uee0e\uee0f\uee10\uee11\uee12\uee13\uee14\uee15\uee16\uee17\uee18\uee19\uee1a\uee1b\uee1c\uee1d\uee1e\uee1f\uee20\uee21\uee22\uee23\uee24\uee25\uee26\uee27\uee28\uee29\uee2a\uee2b\uee2c\uee2d\uee2e\uee2f\uee30\uee31\uee32\uee33\uee34\uee35\uee36\uee37\uee38\uee39\uee3a\uee3b\uee3c\uee3d\uee3e\uee3f\uee40\uee41\uee42\uee43\uee44\uee45\ue
 e46\uee47\uee48\uee49\uee4a\uee4b\uee4c\uee4d\uee4e\uee4f\uee50\uee51\uee52\uee53\uee54\uee55\uee56\uee57\uee58\uee59\uee5a\uee5b\uee5c\uee5d\uee5e\uee5f\uee60\uee61\uee62\uee63\uee64\uee65\uee66\uee67\uee68\uee69\uee6a\uee6b\uee6c\uee6d\uee6e\uee6f\uee70\uee71\uee72\uee73\uee74\uee75\uee76\uee77\uee78\uee79\uee7a\uee7b\uee7c\uee7d\uee7e\uee7f\uee80\uee81\uee82\uee83\uee84\uee85\uee86\uee87\uee88\uee89\uee8a\uee8b\uee8c\uee8d\uee8e\uee8f\uee90\uee91\uee92\uee93\uee94\uee95\uee96\uee97\uee98\uee99\uee9a\uee9b\uee9c\uee9d\uee9e\uee9f\ueea0\ueea1\ueea2\ueea3\ueea4\ueea5\ueea6\ueea7\ueea8\ueea9\ueeaa\ueeab\ueeac\ueead\ueeae\ueeaf\ueeb0\ueeb1\ueeb2\ueeb3\ueeb4\ueeb5\ueeb6\ueeb7\ueeb8\ueeb9\ueeba\ueebb\ueebc\ueebd\ueebe\ueebf\ueec0\ueec1\ueec2\ueec3\ueec4\ueec5\ueec6\ueec7\ueec8\ueec9\ueeca\ueecb\ueecc\ueecd\ueece\ueecf\ueed0\ueed1\ueed2\ueed3\ueed4\ueed5\ueed6\ueed7\ueed8\ueed9\ueeda\ueedb\ueedc\ueedd\ueede\ueedf\ueee0\ueee1\ueee2\ueee3\ueee4\ueee5\ueee6\ueee7\ueee8\ueee9\ueeea\ueeeb\uee
 ec\ueeed\ueeee\ueeef\ueef0\ueef1\ueef2\ueef3\ueef4\ueef5\ueef6\ueef7\ueef8\ueef9\ueefa\ueefb\ueefc\ueefd\ueefe\ueeff\uef00\uef01\uef02\uef03\uef04\uef05\uef06\uef07\uef08\uef09\uef0a\uef0b\uef0c\uef0d\uef0e\uef0f\uef10\uef11\uef12\uef13\uef14\uef15\uef16\uef17\uef18\uef19\uef1a\uef1b\uef1c\uef1d\uef1e\uef1f\uef20\uef21\uef22\uef23\uef24\uef25\uef26\uef27\uef28\uef29\uef2a\uef2b\uef2c\uef2d\uef2e\uef2f\uef30\uef31\uef32\uef33\uef34\uef35\uef36\uef37\uef38\uef39\uef3a\uef3b\uef3c\uef3d\uef3e\uef3f\uef40\uef41\uef42\uef43\uef44\uef45\uef46\uef47\uef48\uef49\uef4a\uef4b\uef4c\uef4d\uef4e\uef4f\uef50\uef51\uef52\uef53\uef54\uef55\uef56\uef57\uef58\uef59\uef5a\uef5b\uef5c\uef5d\uef5e\uef5f\uef60\uef61\uef62\uef63\uef64\uef65\uef66\uef67\uef68\uef69\uef6a\uef6b\uef6c\uef6d\uef6e\uef6f\uef70\uef71\uef72\uef73\uef74\uef75\uef76\uef77\uef78\uef79\uef7a\uef7b\uef7c\uef7d\uef7e\uef7f\uef80\uef81\uef82\uef83\uef84\uef85\uef86\uef87\uef88\uef89\uef8a\uef8b\uef8c\uef8d\uef8e\uef8f\uef90\uef91\uef9
 2\uef93\uef94\uef95\uef96\uef97\uef98\uef99\uef9a\uef9b\uef9c\uef9d\uef9e\uef9f\uefa0\uefa1\uefa2\uefa3\uefa4\uefa5\uefa6\uefa7\uefa8\uefa9\uefaa\uefab\uefac\uefad\uefae\uefaf\uefb0\uefb1\uefb2\uefb3\uefb4\uefb5\uefb6\uefb7\uefb8\uefb9\uefba\uefbb\uefbc\uefbd\uefbe\uefbf\uefc0\uefc1\uefc2\uefc3\uefc4\uefc5\uefc6\uefc7\uefc8\uefc9\uefca\uefcb\uefcc\uefcd\uefce\uefcf\uefd0\uefd1\uefd2\uefd3\uefd4\uefd5\uefd6\uefd7\uefd8\uefd9\uefda\uefdb\uefdc\uefdd\uefde\uefdf\uefe0\uefe1\uefe2\uefe3\uefe4\uefe5\uefe6\uefe7\uefe8\uefe9\uefea\uefeb\uefec\uefed\uefee\uefef\ueff0\ueff1\ueff2\ueff3\ueff4\ueff5\ueff6\ueff7\ueff8\ueff9\ueffa\ueffb\ueffc\ueffd\ueffe\uefff\uf000\uf001\uf002\uf003\uf004\uf005\uf006\uf007\uf008\uf009\uf00a\uf00b\uf00c\uf00d\uf00e\uf00f\uf010\uf011\uf012\uf013\uf014\uf015\uf016\uf017\uf018\uf019\uf01a\uf01b\uf01c\uf01d\uf01e\uf01f\uf020\uf021\uf022\uf023\uf024\uf025\uf026\uf027\uf028\uf029\uf02a\uf02b\uf02c\uf02d\uf02e\uf02f\uf030\uf031\uf032\uf033\uf034\uf035\uf036\uf037\uf038
 \uf039\uf03a\uf03b\uf03c\uf03d\uf03e\uf03f\uf040\uf041\uf042\uf043\uf044\uf045\uf046\uf047\uf048\uf049\uf04a\uf04b\uf04c\uf04d\uf04e\uf04f\uf050\uf051\uf052\uf053\uf054\uf055\uf056\uf057\uf058\uf059\uf05a\uf05b\uf05c\uf05d\uf05e\uf05f\uf060\uf061\uf062\uf063\uf064\uf065\uf066\uf067\uf068\uf069\uf06a\uf06b\uf06c\uf06d\uf06e\uf06f\uf070\uf071\uf072\uf073\uf074\uf075\uf076\uf077\uf078\uf079\uf07a\uf07b\uf07c\uf07d\uf07e\uf07f\uf080\uf081\uf082\uf083\uf084\uf085\uf086\uf087\uf088\uf089\uf08a\uf08b\uf08c\uf08d\uf08e\uf08f\uf090\uf091\uf092\uf093\uf094\uf095\uf096\uf097\uf098\uf099\uf09a\uf09b\uf09c\uf09d\uf09e\uf09f\uf0a0\uf0a1\uf0a2\uf0a3\uf0a4\uf0a5\uf0a6\uf0a7\uf0a8\uf0a9\uf0aa\uf0ab\uf0ac\uf0ad\uf0ae\uf0af\uf0b0\uf0b1\uf0b2\uf0b3\uf0b4\uf0b5\uf0b6\uf0b7\uf0b8\uf0b9\uf0ba\uf0bb\uf0bc\uf0bd\uf0be\uf0bf\uf0c0\uf0c1\uf0c2\uf0c3\uf0c4\uf0c5\uf0c6\uf0c7\uf0c8\uf0c9\uf0ca\uf0cb\uf0cc\uf0cd\uf0ce\uf0cf\uf0d0\uf0d1\uf0d2\uf0d3\uf0d4\uf0d5\uf0d6\uf0d7\uf0d8\uf0d9\uf0da\uf0db\uf0dc\uf0dd\uf0de\
 uf0df\uf0e0\uf0e1\uf0e2\uf0e3\uf0e4\uf0e5\uf0e6\uf0e7\uf0e8\uf0e9\uf0ea\uf0eb\uf0ec\uf0ed\uf0ee\uf0ef\uf0f0\uf0f1\uf0f2\uf0f3\uf0f4\uf0f5\uf0f6\uf0f7\uf0f8\uf0f9\uf0fa\uf0fb\uf0fc\uf0fd\uf0fe\uf0ff\uf100\uf101\uf102\uf103\uf104\uf105\uf106\uf107\uf108\uf109\uf10a\uf10b\uf10c\uf10d\uf10e\uf10f\uf110\uf111\uf112\uf113\uf114\uf115\uf116\uf117\uf118\uf119\uf11a\uf11b\uf11c\uf11d\uf11e\uf11f\uf120\uf121\uf122\uf123\uf124\uf125\uf126\uf127\uf128\uf129\uf12a\uf12b\uf12c\uf12d\uf12e\uf12f\uf130\uf131\uf132\uf133\uf134\uf135\uf136\uf137\uf138\uf139\uf13a\uf13b\uf13c\uf13d\uf13e\uf13f\uf140\uf141\uf142\uf143\uf144\uf145\uf146\uf147\uf148\uf149\uf14a\uf14b\uf14c\uf14d\uf14e\uf14f\uf150\uf151\uf152\uf153\uf154\uf155\uf156\uf157\uf158\uf159\uf15a\uf15b\uf15c\uf15d\uf15e\uf15f\uf160\uf161\uf162\uf163\uf164\uf165\uf166\uf167\uf168\uf169\uf16a\uf16b\uf16c\uf16d\uf16e\uf16f\uf170\uf171\uf172\uf173\uf174\uf175\uf176\uf177\uf178\uf179\uf17a\uf17b\uf17c\uf17d\uf17e\uf17f\uf180\uf181\uf182\uf183\uf184\u
 f185\uf186\uf187\uf188\uf189\uf18a\uf18b\uf18c\uf18d\uf18e\uf18f\uf190\uf191\uf192\uf193\uf194\uf195\uf196\uf197\uf198\uf199\uf19a\uf19b\uf19c\uf19d\uf19e\uf19f\uf1a0\uf1a1\uf1a2\uf1a3\uf1a4\uf1a5\uf1a6\uf1a7\uf1a8\uf1a9\uf1aa\uf1ab\uf1ac\uf1ad\uf1ae\uf1af\uf1b0\uf1b1\uf1b2\uf1b3\uf1b4\uf1b5\uf1b6\uf1b7\uf1b8\uf1b9\uf1ba\uf1bb\uf1bc\uf1bd\uf1be\uf1bf\uf1c0\uf1c1\uf1c2\uf1c3\uf1c4\uf1c5\uf1c6\uf1c7\uf1c8\uf1c9\uf1ca\uf1cb\uf1cc\uf1cd\uf1ce\uf1cf\uf1d0\uf1d1\uf1d2\uf1d3\uf1d4\uf1d5\uf1d6\uf1d7\uf1d8\uf1d9\uf1da\uf1db\uf1dc\uf1dd\uf1de\uf1df\uf1e0\uf1e1\uf1e2\uf1e3\uf1e4\uf1e5\uf1e6\uf1e7\uf1e8\uf1e9\uf1ea\uf1eb\uf1ec\uf1ed\uf1ee\uf1ef\uf1f0\uf1f1\uf1f2\uf1f3\uf1f4\uf1f5\uf1f6\uf1f7\uf1f8\uf1f9\uf1fa\uf1fb\uf1fc\uf1fd\uf1fe\uf1ff\uf200\uf201\uf202\uf203\uf204\uf205\uf206\uf207\uf208\uf209\uf20a\uf20b\uf20c\uf20d\uf20e\uf20f\uf210\uf211\uf212\uf213\uf214\uf215\uf216\uf217\uf218\uf219\uf21a\uf21b\uf21c\uf21d\uf21e\uf21f\uf220\uf221\uf222\uf223\uf224\uf225\uf226\uf227\uf228\uf229\uf22a\uf
 22b\uf22c\uf22d\uf22e\uf22f\uf230\uf231\uf232\uf233\uf234\uf235\uf236\uf237\uf238\uf239\uf23a\uf23b\uf23c\uf23d\uf23e\uf23f\uf240\uf241\uf242\uf243\uf244\uf245\uf246\uf247\uf248\uf249\uf24a\uf24b\uf24c\uf24d\uf24e\uf24f\uf250\uf251\uf252\uf253\uf254\uf255\uf256\uf257\uf258\uf259\uf25a\uf25b\uf25c\uf25d\uf25e\uf25f\uf260\uf261\uf262\uf263\uf264\uf265\uf266\uf267\uf268\uf269\uf26a\uf26b\uf26c\uf26d\uf26e\uf26f\uf270\uf271\uf272\uf273\uf274\uf275\uf276\uf277\uf278\uf279\uf27a\uf27b\uf27c\uf27d\uf27e\uf27f\uf280\uf281\uf282\uf283\uf284\uf285\uf286\uf287\uf288\uf289\uf28a\uf28b\uf28c\uf28d\uf28e\uf28f\uf290\uf291\uf292\uf293\uf294\uf295\uf296\uf297\uf298\uf299\uf29a\uf29b\uf29c\uf29d\uf29e\uf29f\uf2a0\uf2a1\uf2a2\uf2a3\uf2a4\uf2a5\uf2a6\uf2a7\uf2a8\uf2a9\uf2aa\uf2ab\uf2ac\uf2ad\uf2ae\uf2af\uf2b0\uf2b1\uf2b2\uf2b3\uf2b4\uf2b5\uf2b6\uf2b7\uf2b8\uf2b9\uf2ba\uf2bb\uf2bc\uf2bd\uf2be\uf2bf\uf2c0\uf2c1\uf2c2\uf2c3\uf2c4\uf2c5\uf2c6\uf2c7\uf2c8\uf2c9\uf2ca\uf2cb\uf2cc\uf2cd\uf2ce\uf2cf\uf2d0\uf2
 d1\uf2d2\uf2d3\uf2d4\uf2d5\uf2d6\uf2d7\uf2d8\uf2d9\uf2da\uf2db\uf2dc\uf2dd\uf2de\uf2df\uf2e0\uf2e1\uf2e2\uf2e3\uf2e4\uf2e5\uf2e6\uf2e7\uf2e8\uf2e9\uf2ea\uf2eb\uf2ec\uf2ed\uf2ee\uf2ef\uf2f0\uf2f1\uf2f2\uf2f3\uf2f4\uf2f5\uf2f6\uf2f7\uf2f8\uf2f9\uf2fa\uf2fb\uf2fc\uf2fd\uf2fe\uf2ff\uf300\uf301\uf302\uf303\uf304\uf305\uf306\uf307\uf308\uf309\uf30a\uf30b\uf30c\uf30d\uf30e\uf30f\uf310\uf311\uf312\uf313\uf314\uf315\uf316\uf317\uf318\uf319\uf31a\uf31b\uf31c\uf31d\uf31e\uf31f\uf320\uf321\uf322\uf323\uf324\uf325\uf326\uf327\uf328\uf329\uf32a\uf32b\uf32c\uf32d\uf32e\uf32f\uf330\uf331\uf332\uf333\uf334\uf335\uf336\uf337\uf338\uf339\uf33a\uf33b\uf33c\uf33d\uf33e\uf33f\uf340\uf341\uf342\uf343\uf344\uf345\uf346\uf347\uf348\uf349\uf34a\uf34b\uf34c\uf34d\uf34e\uf34f\uf350\uf351\uf352\uf353\uf354\uf355\uf356\uf357\uf358\uf359\uf35a\uf35b\uf35c\uf35d\uf35e\uf35f\uf360\uf361\uf362\uf363\uf364\uf365\uf366\uf367\uf368\uf369\uf36a\uf36b\uf36c\uf36d\uf36e\uf36f\uf370\uf371\uf372\uf373\uf374\uf375\uf376\uf37
 7\uf378\uf379\uf37a\uf37b\uf37c\uf37d\uf37e\uf37f\uf380\uf381\uf382\uf383\uf384\uf385\uf386\uf387\uf388\uf389\uf38a\uf38b\uf38c\uf38d\uf38e\uf38f\uf390\uf391\uf392\uf393\uf394\uf395\uf396\uf397\uf398\uf399\uf39a\uf39b\uf39c\uf39d\uf39e\uf39f\uf3a0\uf3a1\uf3a2\uf3a3\uf3a4\uf3a5\uf3a6\uf3a7\uf3a8\uf3a9\uf3aa\uf3ab\uf3ac\uf3ad\uf3ae\uf3af\uf3b0\uf3b1\uf3b2\uf3b3\uf3b4\uf3b5\uf3b6\uf3b7\uf3b8\uf3b9\uf3ba\uf3bb\uf3bc\uf3bd\uf3be\uf3bf\uf3c0\uf3c1\uf3c2\uf3c3\uf3c4\uf3c5\uf3c6\uf3c7\uf3c8\uf3c9\uf3ca\uf3cb\uf3cc\uf3cd\uf3ce\uf3cf\uf3d0\uf3d1\uf3d2\uf3d3\uf3d4\uf3d5\uf3d6\uf3d7\uf3d8\uf3d9\uf3da\uf3db\uf3dc\uf3dd\uf3de\uf3df\uf3e0\uf3e1\uf3e2\uf3e3\uf3e4\uf3e5\uf3e6\uf3e7\uf3e8\uf3e9\uf3ea\uf3eb\uf3ec\uf3ed\uf3ee\uf3ef\uf3f0\uf3f1\uf3f2\uf3f3\uf3f4\uf3f5\uf3f6\uf3f7\uf3f8\uf3f9\uf3fa\uf3fb\uf3fc\uf3fd\uf3fe\uf3ff\uf400\uf401\uf402\uf403\uf404\uf405\uf406\uf407\uf408\uf409\uf40a\uf40b\uf40c\uf40d\uf40e\uf40f\uf410\uf411\uf412\uf413\uf414\uf415\uf416\uf417\uf418\uf419\uf41a\uf41b\uf41c\uf41d
 \uf41e\uf41f\uf420\uf421\uf422\uf423\uf424\uf425\uf426\uf427\uf428\uf429\uf42a\uf42b\uf42c\uf42d\uf42e\uf42f\uf430\uf431\uf432\uf433\uf434\uf435\uf436\uf437\uf438\uf439\uf43a\uf43b\uf43c\uf43d\uf43e\uf43f\uf440\uf441\uf442\uf443\uf444\uf445\uf446\uf447\uf448\uf449\uf44a\uf44b\uf44c\uf44d\uf44e\uf44f\uf450\uf451\uf452\uf453\uf454\uf455\uf456\uf457\uf458\uf459\uf45a\uf45b\uf45c\uf45d\uf45e\uf45f\uf460\uf461\uf462\uf463\uf464\uf465\uf466\uf467\uf468\uf469\uf46a\uf46b\uf46c\uf46d\uf46e\uf46f\uf470\uf471\uf472\uf473\uf474\uf475\uf476\uf477\uf478\uf479\uf47a\uf47b\uf47c\uf47d\uf47e\uf47f\uf480\uf481\uf482\uf483\uf484\uf485\uf486\uf487\uf488\uf489\uf48a\uf48b\uf48c\uf48d\uf48e\uf48f\uf490\uf491\uf492\uf493\uf494\uf495\uf496\uf497\uf498\uf499\uf49a\uf49b\uf49c\uf49d\uf49e\uf49f\uf4a0\uf4a1\uf4a2\uf4a3\uf4a4\uf4a5\uf4a6\uf4a7\uf4a8\uf4a9\uf4aa\uf4ab\uf4ac\uf4ad\uf4ae\uf4af\uf4b0\uf4b1\uf4b2\uf4b3\uf4b4\uf4b5\uf4b6\uf4b7\uf4b8\uf4b9\uf4ba\uf4bb\uf4bc\uf4bd\uf4be\uf4bf\uf4c0\uf4c1\uf4c2\uf4c3\
 uf4c4\uf4c5\uf4c6\uf4c7\uf4c8\uf4c9\uf4ca\uf4cb\uf4cc\uf4cd\uf4ce\uf4cf\uf4d0\uf4d1\uf4d2\uf4d3\uf4d4\uf4d5\uf4d6\uf4d7\uf4d8\uf4d9\uf4da\uf4db\uf4dc\uf4dd\uf4de\uf4df\uf4e0\uf4e1\uf4e2\uf4e3\uf4e4\uf4e5\uf4e6\uf4e7\uf4e8\uf4e9\uf4ea\uf4eb\uf4ec\uf4ed\uf4ee\uf4ef\uf4f0\uf4f1\uf4f2\uf4f3\uf4f4\uf4f5\uf4f6\uf4f7\uf4f8\uf4f9\uf4fa\uf4fb\uf4fc\uf4fd\uf4fe\uf4ff\uf500\uf501\uf502\uf503\uf504\uf505\uf506\uf507\uf508\uf509\uf50a\uf50b\uf50c\uf50d\uf50e\uf50f\uf510\uf511\uf512\uf513\uf514\uf515\uf516\uf517\uf518\uf519\uf51a\uf51b\uf51c\uf51d\uf51e\uf51f\uf520\uf521\uf522\uf523\uf524\uf525\uf526\uf527\uf528\uf529\uf52a\uf52b\uf52c\uf52d\uf52e\uf52f\uf530\uf531\uf532\uf533\uf534\uf535\uf536\uf537\uf538\uf539\uf53a\uf53b\uf53c\uf53d\uf53e\uf53f\uf540\uf541\uf542\uf543\uf544\uf545\uf546\uf547\uf548\uf549\uf54a\uf54b\uf54c\uf54d\uf54e\uf54f\uf550\uf551\uf552\uf553\uf554\uf555\uf556\uf557\uf558\uf559\uf55a\uf55b\uf55c\uf55d\uf55e\uf55f\uf560\uf561\uf562\uf563\uf564\uf565\uf566\uf567\uf568\uf569\u
 f56a\uf56b\uf56c\uf56d\uf56e\uf56f\uf570\uf571\uf572\uf573\uf574\uf575\uf576\uf577\uf578\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf582\uf583\uf584\uf585\uf586\uf587\uf588\uf589\uf58a\uf58b\uf58c\uf58d\uf58e\uf58f\uf590\uf591\uf592\uf593\uf594\uf595\uf596\uf597\uf598\uf599\uf59a\uf59b\uf59c\uf59d\uf59e\uf59f\uf5a0\uf5a1\uf5a2\uf5a3\uf5a4\uf5a5\uf5a6\uf5a7\uf5a8\uf5a9\uf5aa\uf5ab\uf5ac\uf5ad\uf5ae\uf5af\uf5b0\uf5b1\uf5b2\uf5b3\uf5b4\uf5b5\uf5b6\uf5b7\uf5b8\uf5b9\uf5ba\uf5bb\uf5bc\uf5bd\uf5be\uf5bf\uf5c0\uf5c1\uf5c2\uf5c3\uf5c4\uf5c5\uf5c6\uf5c7\uf5c8\uf5c9\uf5ca\uf5cb\uf5cc\uf5cd\uf5ce\uf5cf\uf5d0\uf5d1\uf5d2\uf5d3\uf5d4\uf5d5\uf5d6\uf5d7\uf5d8\uf5d9\uf5da\uf5db\uf5dc\uf5dd\uf5de\uf5df\uf5e0\uf5e1\uf5e2\uf5e3\uf5e4\uf5e5\uf5e6\uf5e7\uf5e8\uf5e9\uf5ea\uf5eb\uf5ec\uf5ed\uf5ee\uf5ef\uf5f0\uf5f1\uf5f2\uf5f3\uf5f4\uf5f5\uf5f6\uf5f7\uf5f8\uf5f9\uf5fa\uf5fb\uf5fc\uf5fd\uf5fe\uf5ff\uf600\uf601\uf602\uf603\uf604\uf605\uf606\uf607\uf608\uf609\uf60a\uf60b\uf60c\uf60d\uf60e\uf60f\uf
 610\uf611\uf612\uf613\uf614\uf615\uf616\uf617\uf618\uf619\uf61a\uf61b\uf61c\uf61d\uf61e\uf61f\uf620\uf621\uf622\uf623\uf624\uf625\uf626\uf627\uf628\uf629\uf62a\uf62b\uf62c\uf62d\uf62e\uf62f\uf630\uf631\uf632\uf633\uf634\uf635\uf636\uf637\uf638\uf639\uf63a\uf63b\uf63c\uf63d\uf63e\uf63f\uf640\uf641\uf642\uf643\uf644\uf645\uf646\uf647\uf648\uf649\uf64a\uf64b\uf64c\uf64d\uf64e\uf64f\uf650\uf651\uf652\uf653\uf654\uf655\uf656\uf657\uf658\uf659\uf65a\uf65b\uf65c\uf65d\uf65e\uf65f\uf660\uf661\uf662\uf663\uf664\uf665\uf666\uf667\uf668\uf669\uf66a\uf66b\uf66c\uf66d\uf66e\uf66f\uf670\uf671\uf672\uf673\uf674\uf675\uf676\uf677\uf678\uf679\uf67a\uf67b\uf67c\uf67d\uf67e\uf67f\uf680\uf681\uf682\uf683\uf684\uf685\uf686\uf687\uf688\uf689\uf68a\uf68b\uf68c\uf68d\uf68e\uf68f\uf690\uf691\uf692\uf693\uf694\uf695\uf696\uf697\uf698\uf699\uf69a\uf69b\uf69c\uf69d\uf69e\uf69f\uf6a0\uf6a1\uf6a2\uf6a3\uf6a4\uf6a5\uf6a6\uf6a7\uf6a8\uf6a9\uf6aa\uf6ab\uf6ac\uf6ad\uf6ae\uf6af\uf6b0\uf6b1\uf6b2\uf6b3\uf6b4\uf6b5\uf6
 b6\uf6b7\uf6b8\uf6b9\uf6ba\uf6bb\uf6bc\uf6bd\uf6be\uf6bf\uf6c0\uf6c1\uf6c2\uf6c3\uf6c4\uf6c5\uf6c6\uf6c7\uf6c8\uf6c9\uf6ca\uf6cb\uf6cc\uf6cd\uf6ce\uf6cf\uf6d0\uf6d1\uf6d2\uf6d3\uf6d4\uf6d5\uf6d6\uf6d7\uf6d8\uf6d9\uf6da\uf6db\uf6dc\uf6dd\uf6de\uf6df\uf6e0\uf6e1\uf6e2\uf6e3\uf6e4\uf6e5\uf6e6\uf6e7\uf6e8\uf6e9\uf6ea\uf6eb\uf6ec\uf6ed\uf6ee\uf6ef\uf6f0\uf6f1\uf6f2\uf6f3\uf6f4\uf6f5\uf6f6\uf6f7\uf6f8\uf6f9\uf6fa\uf6fb\uf6fc\uf6fd\uf6fe\uf6ff\uf700\uf701\uf702\uf703\uf704\uf705\uf706\uf707\uf708\uf709\uf70a\uf70b\uf70c\uf70d\uf70e\uf70f\uf710\uf711\uf712\uf713\uf714\uf715\uf716\uf717\uf718\uf719\uf71a\uf71b\uf71c\uf71d\uf71e\uf71f\uf720\uf721\uf722\uf723\uf724\uf725\uf726\uf727\uf728\uf729\uf72a\uf72b\uf72c\uf72d\uf72e\uf72f\uf730\uf731\uf732\uf733\uf734\uf735\uf736\uf737\uf738\uf739\uf73a\uf73b\uf73c\uf73d\uf73e\uf73f\uf740\uf741\uf742\uf743\uf744\uf745\uf746\uf747\uf748\uf749\uf74a\uf74b\uf74c\uf74d\uf74e\uf74f\uf750\uf751\uf752\uf753\uf754\uf755\uf756\uf757\uf758\uf759\uf75a\uf75b\uf75
 c\uf75d\uf75e\uf75f\uf760\uf761\uf762\uf763\uf764\uf765\uf766\uf767\uf768\uf769\uf76a\uf76b\uf76c\uf76d\uf76e\uf76f\uf770\uf771\uf772\uf773\uf774\uf775\uf776\uf777\uf778\uf779\uf77a\uf77b\uf77c\uf77d\uf77e\uf77f\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff\uf800\uf801\uf802
 \uf803\uf804\uf805\uf806\uf807\uf808\uf809\uf80a\uf80b\uf80c\uf80d\uf80e\uf80f\uf810\uf811\uf812\uf813\uf814\uf815\uf816\uf817\uf818\uf819\uf81a\uf81b\uf81c\uf81d\uf81e\uf81f\uf820\uf821\uf822\uf823\uf824\uf825\uf826\uf827\uf828\uf829\uf82a\uf82b\uf82c\uf82d\uf82e\uf82f\uf830\uf831\uf832\uf833\uf834\uf835\uf836\uf837\uf838\uf839\uf83a\uf83b\uf83c\uf83d\uf83e\uf83f\uf840\uf841\uf842\uf843\uf844\uf845\uf846\uf847\uf848\uf849\uf84a\uf84b\uf84c\uf84d\uf84e\uf84f\uf850\uf851\uf852\uf853\uf854\uf855\uf856\uf857\uf858\uf859\uf85a\uf85b\uf85c\uf85d\uf85e\uf85f\uf860\uf861\uf862\uf863\uf864\uf865\uf866\uf867\uf868\uf869\uf86a\uf86b\uf86c\uf86d\uf86e\uf86f\uf870\uf871\uf872\uf873\uf874\uf875\uf876\uf877\uf878\uf879\uf87a\uf87b\uf87c\uf87d\uf87e\uf87f\uf880\uf881\uf882\uf883\uf884\uf885\uf886\uf887\uf888\uf889\uf88a\uf88b\uf88c\uf88d\uf88e\uf88f\uf890\uf891\uf892\uf893\uf894\uf895\uf896\uf897\uf898\uf899\uf89a\uf89b\uf89c\uf89d\uf89e\uf89f\uf8a0\uf8a1\uf8a2\uf8a3\uf8a4\uf8a5\uf8a6\uf8a7\uf8a8\
 uf8a9\uf8aa\uf8ab\uf8ac\uf8ad\uf8ae\uf8af\uf8b0\uf8b1\uf8b2\uf8b3\uf8b4\uf8b5\uf8b6\uf8b7\uf8b8\uf8b9\uf8ba\uf8bb\uf8bc\uf8bd\uf8be\uf8bf\uf8c0\uf8c1\uf8c2\uf8c3\uf8c4\uf8c5\uf8c6\uf8c7\uf8c8\uf8c9\uf8ca\uf8cb\uf8cc\uf8cd\uf8ce\uf8cf\uf8d0\uf8d1\uf8d2\uf8d3\uf8d4\uf8d5\uf8d6\uf8d7\uf8d8\uf8d9\uf8da\uf8db\uf8dc\uf8dd\uf8de\uf8df\uf8e0\uf8e1\uf8e2\uf8e3\uf8e4\uf8e5\uf8e6\uf8e7\uf8e8\uf8e9\uf8ea\uf8eb\uf8ec\uf8ed\uf8ee\uf8ef\uf8f0\uf8f1\uf8f2\uf8f3\uf8f4\uf8f5\uf8f6\uf8f7\uf8f8\uf8f9\uf8fa\uf8fb\uf8fc\uf8fd\uf8fe\uf8ff'
-
-try:
-    Cs = eval(r"'\ud800\ud801\ud802\ud803\ud804\ud805\ud806\ud807\ud808\ud809\ud80a\ud80b\ud80c\ud80d\ud80e\ud80f\ud810\ud811\ud812\ud813\ud814\ud815\ud816\ud817\ud818\ud819\ud81a\ud81b\ud81c\ud81d\ud81e\ud81f\ud820\ud821\ud822\ud823\ud824\ud825\ud826\ud827\ud828\ud829\ud82a\ud82b\ud82c\ud82d\ud82e\ud82f\ud830\ud831\ud832\ud833\ud834\ud835\ud836\ud837\ud838\ud839\ud83a\ud83b\ud83c\ud83d\ud83e\ud83f\ud840\ud841\ud842\ud843\ud844\ud845\ud846\ud847\ud848\ud849\ud84a\ud84b\ud84c\ud84d\ud84e\ud84f\ud850\ud851\ud852\ud853\ud854\ud855\ud856\ud857\ud858\ud859\ud85a\ud85b\ud85c\ud85d\ud85e\ud85f\ud860\ud861\ud862\ud863\ud864\ud865\ud866\ud867\ud868\ud869\ud86a\ud86b\ud86c\ud86d\ud86e\ud86f\ud870\ud871\ud872\ud873\ud874\ud875\ud876\ud877\ud878\ud879\ud87a\ud87b\ud87c\ud87d\ud87e\ud87f\ud880\ud881\ud882\ud883\ud884\ud885\ud886\ud887\ud888\ud889\ud88a\ud88b\ud88c\ud88d\ud88e\ud88f\ud890\ud891\ud892\ud893\ud894\ud895\ud896\ud897\ud898\ud899\ud89a\ud89b\ud89c\ud89d\ud89e\ud89f\ud8a0\ud8a1\ud8a2\u
 d8a3\ud8a4\ud8a5\ud8a6\ud8a7\ud8a8\ud8a9\ud8aa\ud8ab\ud8ac\ud8ad\ud8ae\ud8af\ud8b0\ud8b1\ud8b2\ud8b3\ud8b4\ud8b5\ud8b6\ud8b7\ud8b8\ud8b9\ud8ba\ud8bb\ud8bc\ud8bd\ud8be\ud8bf\ud8c0\ud8c1\ud8c2\ud8c3\ud8c4\ud8c5\ud8c6\ud8c7\ud8c8\ud8c9\ud8ca\ud8cb\ud8cc\ud8cd\ud8ce\ud8cf\ud8d0\ud8d1\ud8d2\ud8d3\ud8d4\ud8d5\ud8d6\ud8d7\ud8d8\ud8d9\ud8da\ud8db\ud8dc\ud8dd\ud8de\ud8df\ud8e0\ud8e1\ud8e2\ud8e3\ud8e4\ud8e5\ud8e6\ud8e7\ud8e8\ud8e9\ud8ea\ud8eb\ud8ec\ud8ed\ud8ee\ud8ef\ud8f0\ud8f1\ud8f2\ud8f3\ud8f4\ud8f5\ud8f6\ud8f7\ud8f8\ud8f9\ud8fa\ud8fb\ud8fc\ud8fd\ud8fe\ud8ff\ud900\ud901\ud902\ud903\ud904\ud905\ud906\ud907\ud908\ud909\ud90a\ud90b\ud90c\ud90d\ud90e\ud90f\ud910\ud911\ud912\ud913\ud914\ud915\ud916\ud917\ud918\ud919\ud91a\ud91b\ud91c\ud91d\ud91e\ud91f\ud920\ud921\ud922\ud923\ud924\ud925\ud926\ud927\ud928\ud929\ud92a\ud92b\ud92c\ud92d\ud92e\ud92f\ud930\ud931\ud932\ud933\ud934\ud935\ud936\ud937\ud938\ud939\ud93a\ud93b\ud93c\ud93d\ud93e\ud93f\ud940\ud941\ud942\ud943\ud944\ud945\ud946\ud947\ud948\ud
 949\ud94a\ud94b\ud94c\ud94d\ud94e\ud94f\ud950\ud951\ud952\ud953\ud954\ud955\ud956\ud957\ud958\ud959\ud95a\ud95b\ud95c\ud95d\ud95e\ud95f\ud960\ud961\ud962\ud963\ud964\ud965\ud966\ud967\ud968\ud969\ud96a\ud96b\ud96c\ud96d\ud96e\ud96f\ud970\ud971\ud972\ud973\ud974\ud975\ud976\ud977\ud978\ud979\ud97a\ud97b\ud97c\ud97d\ud97e\ud97f\ud980\ud981\ud982\ud983\ud984\ud985\ud986\ud987\ud988\ud989\ud98a\ud98b\ud98c\ud98d\ud98e\ud98f\ud990\ud991\ud992\ud993\ud994\ud995\ud996\ud997\ud998\ud999\ud99a\ud99b\ud99c\ud99d\ud99e\ud99f\ud9a0\ud9a1\ud9a2\ud9a3\ud9a4\ud9a5\ud9a6\ud9a7\ud9a8\ud9a9\ud9aa\ud9ab\ud9ac\ud9ad\ud9ae\ud9af\ud9b0\ud9b1\ud9b2\ud9b3\ud9b4\ud9b5\ud9b6\ud9b7\ud9b8\ud9b9\ud9ba\ud9bb\ud9bc\ud9bd\ud9be\ud9bf\ud9c0\ud9c1\ud9c2\ud9c3\ud9c4\ud9c5\ud9c6\ud9c7\ud9c8\ud9c9\ud9ca\ud9cb\ud9cc\ud9cd\ud9ce\ud9cf\ud9d0\ud9d1\ud9d2\ud9d3\ud9d4\ud9d5\ud9d6\ud9d7\ud9d8\ud9d9\ud9da\ud9db\ud9dc\ud9dd\ud9de\ud9df\ud9e0\ud9e1\ud9e2\ud9e3\ud9e4\ud9e5\ud9e6\ud9e7\ud9e8\ud9e9\ud9ea\ud9eb\ud9ec\ud9ed\ud9ee\ud9
 ef\ud9f0\ud9f1\ud9f2\ud9f3\ud9f4\ud9f5\ud9f6\ud9f7\ud9f8\ud9f9\ud9fa\ud9fb\ud9fc\ud9fd\ud9fe\ud9ff\uda00\uda01\uda02\uda03\uda04\uda05\uda06\uda07\uda08\uda09\uda0a\uda0b\uda0c\uda0d\uda0e\uda0f\uda10\uda11\uda12\uda13\uda14\uda15\uda16\uda17\uda18\uda19\uda1a\uda1b\uda1c\uda1d\uda1e\uda1f\uda20\uda21\uda22\uda23\uda24\uda25\uda26\uda27\uda28\uda29\uda2a\uda2b\uda2c\uda2d\uda2e\uda2f\uda30\uda31\uda32\uda33\uda34\uda35\uda36\uda37\uda38\uda39\uda3a\uda3b\uda3c\uda3d\uda3e\uda3f\uda40\uda41\uda42\uda43\uda44\uda45\uda46\uda47\uda48\uda49\uda4a\uda4b\uda4c\uda4d\uda4e\uda4f\uda50\uda51\uda52\uda53\uda54\uda55\uda56\uda57\uda58\uda59\uda5a\uda5b\uda5c\uda5d\uda5e\uda5f\uda60\uda61\uda62\uda63\uda64\uda65\uda66\uda67\uda68\uda69\uda6a\uda6b\uda6c\uda6d\uda6e\uda6f\uda70\uda71\uda72\uda73\uda74\uda75\uda76\uda77\uda78\uda79\uda7a\uda7b\uda7c\uda7d\uda7e\uda7f\uda80\uda81\uda82\uda83\uda84\uda85\uda86\uda87\uda88\uda89\uda8a\uda8b\uda8c\uda8d\uda8e\uda8f\uda90\uda91\uda92\uda93\uda94\uda9
 5\uda96\uda97\uda98\uda99\uda9a\uda9b\uda9c\uda9d\uda9e\uda9f\udaa0\udaa1\udaa2\udaa3\udaa4\udaa5\udaa6\udaa7\udaa8\udaa9\udaaa\udaab\udaac\udaad\udaae\udaaf\udab0\udab1\udab2\udab3\udab4\udab5\udab6\udab7\udab8\udab9\udaba\udabb\udabc\udabd\udabe\udabf\udac0\udac1\udac2\udac3\udac4\udac5\udac6\udac7\udac8\udac9\udaca\udacb\udacc\udacd\udace\udacf\udad0\udad1\udad2\udad3\udad4\udad5\udad6\udad7\udad8\udad9\udada\udadb\udadc\udadd\udade\udadf\udae0\udae1\udae2\udae3\udae4\udae5\udae6\udae7\udae8\udae9\udaea\udaeb\udaec\udaed\udaee\udaef\udaf0\udaf1\udaf2\udaf3\udaf4\udaf5\udaf6\udaf7\udaf8\udaf9\udafa\udafb\udafc\udafd\udafe\udaff\udb00\udb01\udb02\udb03\udb04\udb05\udb06\udb07\udb08\udb09\udb0a\udb0b\udb0c\udb0d\udb0e\udb0f\udb10\udb11\udb12\udb13\udb14\udb15\udb16\udb17\udb18\udb19\udb1a\udb1b\udb1c\udb1d\udb1e\udb1f\udb20\udb21\udb22\udb23\udb24\udb25\udb26\udb27\udb28\udb29\udb2a\udb2b\udb2c\udb2d\udb2e\udb2f\udb30\udb31\udb32\udb33\udb34\udb35\udb36\udb37\udb38\udb39\udb3a\udb3b
 \udb3c\udb3d\udb3e\udb3f\udb40\udb41\udb42\udb43\udb44\udb45\udb46\udb47\udb48\udb49\udb4a\udb4b\udb4c\udb4d\udb4e\udb4f\udb50\udb51\udb52\udb53\udb54\udb55\udb56\udb57\udb58\udb59\udb5a\udb5b\udb5c\udb5d\udb5e\udb5f\udb60\udb61\udb62\udb63\udb64\udb65\udb66\udb67\udb68\udb69\udb6a\udb6b\udb6c\udb6d\udb6e\udb6f\udb70\udb71\udb72\udb73\udb74\udb75\udb76\udb77\udb78\udb79\udb7a\udb7b\udb7c\udb7d\udb7e\udb7f\udb80\udb81\udb82\udb83\udb84\udb85\udb86\udb87\udb88\udb89\udb8a\udb8b\udb8c\udb8d\udb8e\udb8f\udb90\udb91\udb92\udb93\udb94\udb95\udb96\udb97\udb98\udb99\udb9a\udb9b\udb9c\udb9d\udb9e\udb9f\udba0\udba1\udba2\udba3\udba4\udba5\udba6\udba7\udba8\udba9\udbaa\udbab\udbac\udbad\udbae\udbaf\udbb0\udbb1\udbb2\udbb3\udbb4\udbb5\udbb6\udbb7\udbb8\udbb9\udbba\udbbb\udbbc\udbbd\udbbe\udbbf\udbc0\udbc1\udbc2\udbc3\udbc4\udbc5\udbc6\udbc7\udbc8\udbc9\udbca\udbcb\udbcc\udbcd\udbce\udbcf\udbd0\udbd1\udbd2\udbd3\udbd4\udbd5\udbd6\udbd7\udbd8\udbd9\udbda\udbdb\udbdc\udbdd\udbde\udbdf\udbe0\udbe1\
 udbe2\udbe3\udbe4\udbe5\udbe6\udbe7\udbe8\udbe9\udbea\udbeb\udbec\udbed\udbee\udbef\udbf0\udbf1\udbf2\udbf3\udbf4\udbf5\udbf6\udbf7\udbf8\udbf9\udbfa\udbfb\udbfc\udbfd\udbfe\U0010fc00\udc01\udc02\udc03\udc04\udc05\udc06\udc07\udc08\udc09\udc0a\udc0b\udc0c\udc0d\udc0e\udc0f\udc10\udc11\udc12\udc13\udc14\udc15\udc16\udc17\udc18\udc19\udc1a\udc1b\udc1c\udc1d\udc1e\udc1f\udc20\udc21\udc22\udc23\udc24\udc25\udc26\udc27\udc28\udc29\udc2a\udc2b\udc2c\udc2d\udc2e\udc2f\udc30\udc31\udc32\udc33\udc34\udc35\udc36\udc37\udc38\udc39\udc3a\udc3b\udc3c\udc3d\udc3e\udc3f\udc40\udc41\udc42\udc43\udc44\udc45\udc46\udc47\udc48\udc49\udc4a\udc4b\udc4c\udc4d\udc4e\udc4f\udc50\udc51\udc52\udc53\udc54\udc55\udc56\udc57\udc58\udc59\udc5a\udc5b\udc5c\udc5d\udc5e\udc5f\udc60\udc61\udc62\udc63\udc64\udc65\udc66\udc67\udc68\udc69\udc6a\udc6b\udc6c\udc6d\udc6e\udc6f\udc70\udc71\udc72\udc73\udc74\udc75\udc76\udc77\udc78\udc79\udc7a\udc7b\udc7c\udc7d\udc7e\udc7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc
 88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff\udd00\udd01\udd02\udd03\udd04\udd05\udd06\udd07\udd08\udd09\udd0a\udd0b\udd0c\udd0d\udd0e\udd0f\udd10\udd11\udd12\udd13\udd14\udd15\udd16\udd17\udd18\udd19\udd1a\udd1b\udd1c\udd1d\udd1e\udd1f\udd20\udd21\udd22\udd23\udd24\udd25\udd26\udd27\udd28\udd29\udd2a\udd2b\udd2c\udd2d\udd2
 e\udd2f\udd30\udd31\udd32\udd33\udd34\udd35\udd36\udd37\udd38\udd39\udd3a\udd3b\udd3c\udd3d\udd3e\udd3f\udd40\udd41\udd42\udd43\udd44\udd45\udd46\udd47\udd48\udd49\udd4a\udd4b\udd4c\udd4d\udd4e\udd4f\udd50\udd51\udd52\udd53\udd54\udd55\udd56\udd57\udd58\udd59\udd5a\udd5b\udd5c\udd5d\udd5e\udd5f\udd60\udd61\udd62\udd63\udd64\udd65\udd66\udd67\udd68\udd69\udd6a\udd6b\udd6c\udd6d\udd6e\udd6f\udd70\udd71\udd72\udd73\udd74\udd75\udd76\udd77\udd78\udd79\udd7a\udd7b\udd7c\udd7d\udd7e\udd7f\udd80\udd81\udd82\udd83\udd84\udd85\udd86\udd87\udd88\udd89\udd8a\udd8b\udd8c\udd8d\udd8e\udd8f\udd90\udd91\udd92\udd93\udd94\udd95\udd96\udd97\udd98\udd99\udd9a\udd9b\udd9c\udd9d\udd9e\udd9f\udda0\udda1\udda2\udda3\udda4\udda5\udda6\udda7\udda8\udda9\uddaa\uddab\uddac\uddad\uddae\uddaf\uddb0\uddb1\uddb2\uddb3\uddb4\uddb5\uddb6\uddb7\uddb8\uddb9\uddba\uddbb\uddbc\uddbd\uddbe\uddbf\uddc0\uddc1\uddc2\uddc3\uddc4\uddc5\uddc6\uddc7\uddc8\uddc9\uddca\uddcb\uddcc\uddcd\uddce\uddcf\uddd0\uddd1\uddd2\uddd3\uddd4
 \uddd5\uddd6\uddd7\uddd8\uddd9\uddda\udddb\udddc\udddd\uddde\udddf\udde0\udde1\udde2\udde3\udde4\udde5\udde6\udde7\udde8\udde9\uddea\uddeb\uddec\udded\uddee\uddef\uddf0\uddf1\uddf2\uddf3\uddf4\uddf5\uddf6\uddf7\uddf8\uddf9\uddfa\uddfb\uddfc\uddfd\uddfe\uddff\ude00\ude01\ude02\ude03\ude04\ude05\ude06\ude07\ude08\ude09\ude0a\ude0b\ude0c\ude0d\ude0e\ude0f\ude10\ude11\ude12\ude13\ude14\ude15\ude16\ude17\ude18\ude19\ude1a\ude1b\ude1c\ude1d\ude1e\ude1f\ude20\ude21\ude22\ude23\ude24\ude25\ude26\ude27\ude28\ude29\ude2a\ude2b\ude2c\ude2d\ude2e\ude2f\ude30\ude31\ude32\ude33\ude34\ude35\ude36\ude37\ude38\ude39\ude3a\ude3b\ude3c\ude3d\ude3e\ude3f\ude40\ude41\ude42\ude43\ude44\ude45\ude46\ude47\ude48\ude49\ude4a\ude4b\ude4c\ude4d\ude4e\ude4f\ude50\ude51\ude52\ude53\ude54\ude55\ude56\ude57\ude58\ude59\ude5a\ude5b\ude5c\ude5d\ude5e\ude5f\ude60\ude61\ude62\ude63\ude64\ude65\ude66\ude67\ude68\ude69\ude6a\ude6b\ude6c\ude6d\ude6e\ude6f\ude70\ude71\ude72\ude73\ude74\ude75\ude76\ude77\ude78\ude79\ude7a\
 ude7b\ude7c\ude7d\ude7e\ude7f\ude80\ude81\ude82\ude83\ude84\ude85\ude86\ude87\ude88\ude89\ude8a\ude8b\ude8c\ude8d\ude8e\ude8f\ude90\ude91\ude92\ude93\ude94\ude95\ude96\ude97\ude98\ude99\ude9a\ude9b\ude9c\ude9d\ude9e\ude9f\udea0\udea1\udea2\udea3\udea4\udea5\udea6\udea7\udea8\udea9\udeaa\udeab\udeac\udead\udeae\udeaf\udeb0\udeb1\udeb2\udeb3\udeb4\udeb5\udeb6\udeb7\udeb8\udeb9\udeba\udebb\udebc\udebd\udebe\udebf\udec0\udec1\udec2\udec3\udec4\udec5\udec6\udec7\udec8\udec9\udeca\udecb\udecc\udecd\udece\udecf\uded0\uded1\uded2\uded3\uded4\uded5\uded6\uded7\uded8\uded9\udeda\udedb\udedc\udedd\udede\udedf\udee0\udee1\udee2\udee3\udee4\udee5\udee6\udee7\udee8\udee9\udeea\udeeb\udeec\udeed\udeee\udeef\udef0\udef1\udef2\udef3\udef4\udef5\udef6\udef7\udef8\udef9\udefa\udefb\udefc\udefd\udefe\udeff\udf00\udf01\udf02\udf03\udf04\udf05\udf06\udf07\udf08\udf09\udf0a\udf0b\udf0c\udf0d\udf0e\udf0f\udf10\udf11\udf12\udf13\udf14\udf15\udf16\udf17\udf18\udf19\udf1a\udf1b\udf1c\udf1d\udf1e\udf1f\udf20\u
 df21\udf22\udf23\udf24\udf25\udf26\udf27\udf28\udf29\udf2a\udf2b\udf2c\udf2d\udf2e\udf2f\udf30\udf31\udf32\udf33\udf34\udf35\udf36\udf37\udf38\udf39\udf3a\udf3b\udf3c\udf3d\udf3e\udf3f\udf40\udf41\udf42\udf43\udf44\udf45\udf46\udf47\udf48\udf49\udf4a\udf4b\udf4c\udf4d\udf4e\udf4f\udf50\udf51\udf52\udf53\udf54\udf55\udf56\udf57\udf58\udf59\udf5a\udf5b\udf5c\udf5d\udf5e\udf5f\udf60\udf61\udf62\udf63\udf64\udf65\udf66\udf67\udf68\udf69\udf6a\udf6b\udf6c\udf6d\udf6e\udf6f\udf70\udf71\udf72\udf73\udf74\udf75\udf76\udf77\udf78\udf79\udf7a\udf7b\udf7c\udf7d\udf7e\udf7f\udf80\udf81\udf82\udf83\udf84\udf85\udf86\udf87\udf88\udf89\udf8a\udf8b\udf8c\udf8d\udf8e\udf8f\udf90\udf91\udf92\udf93\udf94\udf95\udf96\udf97\udf98\udf99\udf9a\udf9b\udf9c\udf9d\udf9e\udf9f\udfa0\udfa1\udfa2\udfa3\udfa4\udfa5\udfa6\udfa7\udfa8\udfa9\udfaa\udfab\udfac\udfad\udfae\udfaf\udfb0\udfb1\udfb2\udfb3\udfb4\udfb5\udfb6\udfb7\udfb8\udfb9\udfba\udfbb\udfbc\udfbd\udfbe\udfbf\udfc0\udfc1\udfc2\udfc3\udfc4\udfc5\udfc6\ud
 fc7\udfc8\udfc9\udfca\udfcb\udfcc\udfcd\udfce\udfcf\udfd0\udfd1\udfd2\udfd3\udfd4\udfd5\udfd6\udfd7\udfd8\udfd9\udfda\udfdb\udfdc\udfdd\udfde\udfdf\udfe0\udfe1\udfe2\udfe3\udfe4\udfe5\udfe6\udfe7\udfe8\udfe9\udfea\udfeb\udfec\udfed\udfee\udfef\udff0\udff1\udff2\udff3\udff4\udff5\udff6\udff7\udff8\udff9\udffa\udffb\udffc\udffd\udffe\udfff'")
-except UnicodeDecodeError:
-    Cs = '' # Jython can't handle isolated surrogates
-
-Ll = u'abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u
 0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u0234\u0235\u0236\u0237\u0238\u0239\u023c\u023f\u0240\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d\u028e\u028f\u0290\u0291\u0292\u0293\u0294\u0295\u0296\u0297\u0298\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac\u02ad\u02ae\u02af\u0390\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u0
 3ef\u03f0\u03f1\u03f2\u03f3\u03f5\u03f8\u03fb\u03fc\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0561\u0562\u0563\u0564\u0565\u0566\u0567\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b\u057c\u057d\u05
 7e\u057f\u0580\u0581\u0582\u0583\u0584\u0585\u0586\u0587\u1d00\u1d01\u1d02\u1d03\u1d04\u1d05\u1d06\u1d07\u1d08\u1d09\u1d0a\u1d0b\u1d0c\u1d0d\u1d0e\u1d0f\u1d10\u1d11\u1d12\u1d13\u1d14\u1d15\u1d16\u1d17\u1d18\u1d19\u1d1a\u1d1b\u1d1c\u1d1d\u1d1e\u1d1f\u1d20\u1d21\u1d22\u1d23\u1d24\u1d25\u1d26\u1d27\u1d28\u1d29\u1d2a\u1d2b\u1d62\u1d63\u1d64\u1d65\u1d66\u1d67\u1d68\u1d69\u1d6a\u1d6b\u1d6c\u1d6d\u1d6e\u1d6f\u1d70\u1d71\u1d72\u1d73\u1d74\u1d75\u1d76\u1d77\u1d79\u1d7a\u1d7b\u1d7c\u1d7d\u1d7e\u1d7f\u1d80\u1d81\u1d82\u1d83\u1d84\u1d85\u1d86\u1d87\u1d88\u1d89\u1d8a\u1d8b\u1d8c\u1d8d\u1d8e\u1d8f\u1d90\u1d91\u1d92\u1d93\u1d94\u1d95\u1d96\u1d97\u1d98\u1d99\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e7
 1\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98\u1e99\u1e9a\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6\u1fb7
 \u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1ff7\u2071\u207f\u210a\u210e\u210f\u2113\u212f\u2134\u2139\u213c

<TRUNCATED>

[13/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst b/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst
deleted file mode 100644
index 912bd39..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst
+++ /dev/null
@@ -1,168 +0,0 @@
-Introduction
-============
-
-This is the documentation for the Jinja2 general purpose templating language.
-Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
-fast and secure.
-
-If you have any exposure to other text-based template languages, such as Smarty or
-Django, you should feel right at home with Jinja2.  It's both designer and
-developer friendly by sticking to Python's principles and adding functionality
-useful for templating environments.
-
-The key-features are...
-
--   ... **configurable syntax**.  If you are generating LaTeX or other formats
-    with Jinja2 you can change the delimiters to something that integrates better
-    into the LaTeX markup.
-
--   ... **fast**.  While performance is not the primarily target of Jinja2 it's
-    surprisingly fast.  The overhead compared to regular Python code was reduced
-    to the very minimum.
-
--   ... **easy to debug**.  Jinja2 integrates directly into the python traceback
-    system which allows you to debug Jinja2 templates with regular python
-    debugging helpers.
-
--   ... **secure**.  It's possible to evaluate untrusted template code if the
-    optional sandbox is enabled.  This allows Jinja2 to be used as templating
-    language for applications where users may modify the template design.
-
-
-Prerequisites
--------------
-
-Jinja2 needs at least **Python 2.4** to run.  Additionally a working C-compiler
-that can create python extensions should be installed for the debugger if you
-are using Python 2.4.
-
-If you don't have a working C-compiler and you are trying to install the source
-release with the debugsupport you will get a compiler error.
-
-.. _ctypes: http://python.net/crew/theller/ctypes/
-
-
-Installation
-------------
-
-You have multiple ways to install Jinja2.  If you are unsure what to do, go
-with the Python egg or tarball.
-
-As a Python egg (via easy_install)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can install the most recent Jinja2 version using `easy_install`_ or `pip`_::
-
-    easy_install Jinja2
-    pip install Jinja2
-
-This will install a Jinja2 egg in your Python installation's site-packages
-directory.
-
-(If you are installing from the windows command line omit the `sudo` and make
-sure to run the command as user with administrator rights)
-
-From the tarball release
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1.  Download the most recent tarball from the `download page`_
-2.  Unpack the tarball
-3.  ``sudo python setup.py install``
-
-Note that you either have to have setuptools or `distribute`_ installed,
-the latter is preferred.
-
-This will install Jinja2 into your Python installation's site-packages directory.
-
-.. _distribute: http://pypi.python.org/pypi/distribute
-
-Installing the development version
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1.  Install `git`_
-2.  ``git clone git://github.com/mitsuhiko/ambari_jinja2.git``
-3.  ``cd ambari_jinja2``
-4.  ``ln -s ambari_jinja2 /usr/lib/python2.X/site-packages``
-
-As an alternative to steps 4 you can also do ``python setup.py develop``
-which will install the package via distribute in development mode.  This also
-has the advantage that the C extensions are compiled.
-
-.. _download page: http://pypi.python.org/pypi/Jinja2
-.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
-.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
-.. _pip: http://pypi.python.org/pypi/pip
-.. _git: http://git-scm.org/
-
-
-More Speed with MarkupSafe
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-As of version 2.5.1 Jinja2 will check for an installed `MarkupSafe`_
-module.  If it can find it, it will use the Markup class of that module
-instead of the one that comes with Jinja2.  `MarkupSafe` replaces the
-older speedups module that came with Jinja2 and has the advantage that is
-has a better setup script and will automatically attempt to install the C
-version and nicely fall back to a pure Python implementation if that is
-not possible.
-
-The C implementation of MarkupSafe is much faster and recommended when
-using Jinja2 with autoescaping.
-
-.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
-
-
-Enable the debug support Module
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-By default Jinja2 will not compile the debug support module.  Enabling this
-will fail if you don't have the Python headers or a working compiler.  This
-is often the case if you are installing Jinja2 from a windows machine.
-
-Because the debug support is only necessary for Python 2.4 you will not
-have to do this unless you run 2.4::
-
-    sudo python setup.py --with-debugsupport install
-
-
-Basic API Usage
----------------
-
-This section gives you a brief introduction to the Python API for Jinja2
-templates.
-
-The most basic way to create a template and render it is through
-:class:`~ambari_jinja2.Template`.  This however is not the recommended way to
-work with it if your templates are not loaded from strings but the file
-system or another data source:
-
->>> from ambari_jinja2 import Template
->>> template = Template('Hello {{ name }}!')
->>> template.render(name='John Doe')
-u'Hello John Doe!'
-
-By creating an instance of :class:`~ambari_jinja2.Template` you get back a new template
-object that provides a method called :meth:`~ambari_jinja2.Template.render` which when
-called with a dict or keyword arguments expands the template.  The dict
-or keywords arguments passed to the template are the so-called "context"
-of the template.
-
-What you can see here is that Jinja2 is using unicode internally and the
-return value is an unicode string.  So make sure that your application is
-indeed using unicode internally.
-
-
-Experimental Python 3 Support
------------------------------
-
-Jinja 2.3 brings experimental support for Python 3.  It means that all
-unittests pass on the new version, but there might still be small bugs in
-there and behavior might be inconsistent.  If you notice any bugs, please
-provide feedback in the `Jinja bug tracker`_.
-
-Also please keep in mind that the documentation is written with Python 2
-in mind, you will have to adapt the shown code examples to Python 3 syntax
-for yourself.
-
-
-.. _Jinja bug tracker: http://github.com/mitsuhiko/ambari_jinja2/issues

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py b/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py
deleted file mode 100644
index da95354..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    Jinja Documentation Extensions
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Support for automatically documenting filters and tests.
-
-    :copyright: Copyright 2008 by Armin Ronacher.
-    :license: BSD.
-"""
-import os
-import re
-import inspect
-import ambari_jinja2
-from itertools import islice
-from types import BuiltinFunctionType
-from docutils import nodes
-from docutils.statemachine import ViewList
-from sphinx.ext.autodoc import prepare_docstring
-from sphinx.application import TemplateBridge
-from pygments.style import Style
-from pygments.token import Keyword, Name, Comment, String, Error, \
-     Number, Operator, Generic
-from ambari_jinja2 import Environment, FileSystemLoader
-
-
-def parse_rst(state, content_offset, doc):
-    node = nodes.section()
-    # hack around title style bookkeeping
-    surrounding_title_styles = state.memo.title_styles
-    surrounding_section_level = state.memo.section_level
-    state.memo.title_styles = []
-    state.memo.section_level = 0
-    state.nested_parse(doc, content_offset, node, match_titles=1)
-    state.memo.title_styles = surrounding_title_styles
-    state.memo.section_level = surrounding_section_level
-    return node.children
-
-
-class JinjaStyle(Style):
-    title = 'Jinja Style'
-    default_style = ""
-    styles = {
-        Comment:                    'italic #aaaaaa',
-        Comment.Preproc:            'noitalic #B11414',
-        Comment.Special:            'italic #505050',
-
-        Keyword:                    'bold #B80000',
-        Keyword.Type:               '#808080',
-
-        Operator.Word:              'bold #B80000',
-
-        Name.Builtin:               '#333333',
-        Name.Function:              '#333333',
-        Name.Class:                 'bold #333333',
-        Name.Namespace:             'bold #333333',
-        Name.Entity:                'bold #363636',
-        Name.Attribute:             '#686868',
-        Name.Tag:                   'bold #686868',
-        Name.Decorator:             '#686868',
-
-        String:                     '#AA891C',
-        Number:                     '#444444',
-
-        Generic.Heading:            'bold #000080',
-        Generic.Subheading:         'bold #800080',
-        Generic.Deleted:            '#aa0000',
-        Generic.Inserted:           '#00aa00',
-        Generic.Error:              '#aa0000',
-        Generic.Emph:               'italic',
-        Generic.Strong:             'bold',
-        Generic.Prompt:             '#555555',
-        Generic.Output:             '#888888',
-        Generic.Traceback:          '#aa0000',
-
-        Error:                      '#F00 bg:#FAA'
-    }
-
-
-_sig_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))')
-
-
-def format_function(name, aliases, func):
-    lines = inspect.getdoc(func).splitlines()
-    signature = '()'
-    if isinstance(func, BuiltinFunctionType):
-        match = _sig_re.match(lines[0])
-        if match is not None:
-            del lines[:1 + bool(lines and not lines[0])]
-            signature = match.group(1)
-    else:
-        try:
-            argspec = inspect.getargspec(func)
-            if getattr(func, 'environmentfilter', False) or \
-               getattr(func, 'contextfilter', False):
-                del argspec[0][0]
-            signature = inspect.formatargspec(*argspec)
-        except:
-            pass
-    result = ['.. function:: %s%s' % (name, signature), '']
-    result.extend('    ' + line for line in lines)
-    if aliases:
-        result.extend(('', '    :aliases: %s' % ', '.join(
-                      '``%s``' % x for x in sorted(aliases))))
-    return result
-
-
-def dump_functions(mapping):
-    def directive(dirname, arguments, options, content, lineno,
-                      content_offset, block_text, state, state_machine):
-        reverse_mapping = {}
-        for name, func in mapping.iteritems():
-            reverse_mapping.setdefault(func, []).append(name)
-        filters = []
-        for func, names in reverse_mapping.iteritems():
-            aliases = sorted(names, key=lambda x: len(x))
-            name = aliases.pop()
-            filters.append((name, aliases, func))
-        filters.sort()
-
-        result = ViewList()
-        for name, aliases, func in filters:
-            for item in format_function(name, aliases, func):
-                result.append(item, '<jinjaext>')
-
-        node = nodes.paragraph()
-        state.nested_parse(result, content_offset, node)
-        return node.children
-    return directive
-
-
-from ambari_jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS
-jinja_filters = dump_functions(DEFAULT_FILTERS)
-jinja_tests = dump_functions(DEFAULT_TESTS)
-
-
-def jinja_nodes(dirname, arguments, options, content, lineno,
-                content_offset, block_text, state, state_machine):
-    from ambari_jinja2.nodes import Node
-    doc = ViewList()
-    def walk(node, indent):
-        p = ' ' * indent
-        sig = ', '.join(node.fields)
-        doc.append(p + '.. autoclass:: %s(%s)' % (node.__name__, sig), '')
-        if node.abstract:
-            members = []
-            for key, name in node.__dict__.iteritems():
-                if not key.startswith('_') and \
-                   not hasattr(node.__base__, key) and callable(name):
-                    members.append(key)
-            if members:
-                members.sort()
-                doc.append('%s :members: %s' % (p, ', '.join(members)), '')
-        if node.__base__ != object:
-            doc.append('', '')
-            doc.append('%s :Node type: :class:`%s`' %
-                       (p, node.__base__.__name__), '')
-        doc.append('', '')
-        children = node.__subclasses__()
-        children.sort(key=lambda x: x.__name__.lower())
-        for child in children:
-            walk(child, indent)
-    walk(Node, 0)
-    return parse_rst(state, content_offset, doc)
-
-
-def inject_toc(app, doctree, docname):
-    titleiter = iter(doctree.traverse(nodes.title))
-    try:
-        # skip first title, we are not interested in that one
-        titleiter.next()
-        title = titleiter.next()
-        # and check if there is at least another title
-        titleiter.next()
-    except StopIteration:
-        return
-    tocnode = nodes.section('')
-    tocnode['classes'].append('toc')
-    toctitle = nodes.section('')
-    toctitle['classes'].append('toctitle')
-    toctitle.append(nodes.title(text='Table Of Contents'))
-    tocnode.append(toctitle)
-    tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1]
-    title.parent.insert(title.parent.children.index(title), tocnode)
-
-
-def setup(app):
-    app.add_directive('jinjafilters', jinja_filters, 0, (0, 0, 0))
-    app.add_directive('jinjatests', jinja_tests, 0, (0, 0, 0))
-    app.add_directive('jinjanodes', jinja_nodes, 0, (0, 0, 0))
-    # uncomment for inline toc.  links are broken unfortunately
-    ##app.connect('doctree-resolved', inject_toc)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst b/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst
deleted file mode 100644
index d008408..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-Sandbox
-=======
-
-The Jinja2 sandbox can be used to evaluate untrusted code.  Access to unsafe
-attributes and methods is prohibited.
-
-Assuming `env` is a :class:`SandboxedEnvironment` in the default configuration
-the following piece of code shows how it works:
-
->>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
-u''
->>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
-Traceback (most recent call last):
-  ...
-SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
-
-
-.. module:: ambari_jinja2.sandbox
-
-.. autoclass:: SandboxedEnvironment([options])
-    :members: is_safe_attribute, is_safe_callable
-
-.. autoclass:: ImmutableSandboxedEnvironment([options])
-
-.. autoexception:: SecurityError
-
-.. autofunction:: unsafe
-
-.. autofunction:: is_internal_attribute
-
-.. autofunction:: modifies_known_mutable
-
-.. admonition:: Note
-
-    The Jinja2 sandbox alone is no solution for perfect security.  Especially
-    for web applications you have to keep in mind that users may create
-    templates with arbitrary HTML in so it's crucial to ensure that (if you
-    are running multiple users on the same server) they can't harm each other
-    via JavaScript insertions and much more.
-
-    Also the sandbox is only as good as the configuration.  We stronly
-    recommend only passing non-shared resources to the template and use
-    some sort of whitelisting for attributes.
-
-    Also keep in mind that templates may raise runtime or compile time errors,
-    so make sure to catch them.

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst b/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst
deleted file mode 100644
index ba3cfb1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst
+++ /dev/null
@@ -1,242 +0,0 @@
-Switching from other Template Engines
-=====================================
-
-.. highlight:: html+jinja
-
-If you have used a different template engine in the past and want to swtich
-to Jinja2 here is a small guide that shows the basic syntatic and semantic
-changes between some common, similar text template engines for Python.
-
-Jinja1
-------
-
-Jinja2 is mostly compatible with Jinja1 in terms of API usage and template
-syntax.  The differences between Jinja1 and 2 are explained in the following
-list.
-
-API
-~~~
-
-Loaders
-    Jinja2 uses a different loader API.  Because the internal representation
-    of templates changed there is no longer support for external caching
-    systems such as memcached.  The memory consumed by templates is comparable
-    with regular Python modules now and external caching doesn't give any
-    advantage.  If you have used a custom loader in the past have a look at
-    the new :ref:`loader API <loaders>`.
-
-Loading templates from strings
-    In the past it was possible to generate templates from a string with the
-    default environment configuration by using `jinja.from_string`.  Jinja2
-    provides a :class:`Template` class that can be used to do the same, but
-    with optional additional configuration.
-
-Automatic unicode conversion
-    Jinja1 performed automatic conversion of bytestrings in a given encoding
-    into unicode objects.  This conversion is no longer implemented as it
-    was inconsistent as most libraries are using the regular Python ASCII
-    bytestring to Unicode conversion.  An application powered by Jinja2
-    *has to* use unicode internally everywhere or make sure that Jinja2 only
-    gets unicode strings passed.
-
-i18n
-    Jinja1 used custom translators for internationalization.  i18n is now
-    available as Jinja2 extension and uses a simpler, more gettext friendly
-    interface and has support for babel.  For more details see
-    :ref:`i18n-extension`.
-
-Internal methods
-    Jinja1 exposed a few internal methods on the environment object such
-    as `call_function`, `get_attribute` and others.  While they were marked
-    as being an internal method it was possible to override them.  Jinja2
-    doesn't have equivalent methods.
-
-Sandbox
-    Jinja1 was running sandbox mode by default.  Few applications actually
-    used that feature so it became optional in Jinja2.  For more details
-    about the sandboxed execution see :class:`SandboxedEnvironment`.
-
-Context
-    Jinja1 had a stacked context as storage for variables passed to the
-    environment.  In Jinja2 a similar object exists but it doesn't allow
-    modifications nor is it a singleton.  As inheritance is dynamic now
-    multiple context objects may exist during template evaluation.
-
-Filters and Tests
-    Filters and tests are regular functions now.  It's no longer necessary
-    and allowed to use factory functions.
-
-
-Templates
-~~~~~~~~~
-
-Jinja2 has mostly the same syntax as Jinja1.  What's different is that
-macros require parentheses around the argument list now.
-
-Additionally Jinja2 allows dynamic inheritance now and dynamic includes.
-The old helper function `rendertemplate` is gone now, `include` can be used
-instead.  Includes no longer import macros and variable assignments, for
-that the new `import` tag is used.  This concept is explained in the
-:ref:`import` documentation.
-
-Another small change happened in the `for`-tag.  The special loop variable
-doesn't have a `parent` attribute, instead you have to alias the loop
-yourself.  See :ref:`accessing-the-parent-loop` for more details.
-
-
-Django
-------
-
-If you have previously worked with Django templates, you should find
-Jinja2 very familiar.  In fact, most of the syntax elements look and
-work the same.
-
-However, Jinja2 provides some more syntax elements covered in the
-documentation and some work a bit different.
-
-This section covers the template changes.  As the API is fundamentally
-different we won't cover it here.
-
-Method Calls
-~~~~~~~~~~~~
-
-In Django method calls work implicitly.  With Jinja2 you have to specify that
-you want to call an object.  Thus this Django code::
-
-    {% for page in user.get_created_pages %}
-        ...
-    {% endfor %}
-    
-will look like this in Jinja::
-
-    {% for page in user.get_created_pages() %}
-        ...
-    {% endfor %}
-
-This allows you to pass variables to the function which is also used for macros
-which is not possible in Django.
-
-Conditions
-~~~~~~~~~~
-
-In Django you can use the following constructs to check for equality::
-
-    {% ifequal foo "bar" %}
-        ...
-    {% else %}
-        ...
-    {% endifequal %}
-
-In Jinja2 you can use the normal if statement in combination with operators::
-
-    {% if foo == 'bar' %}
-        ...
-    {% else %}
-        ...
-    {% endif %}
-
-You can also have multiple elif branches in your template::
-
-    {% if something %}
-        ...
-    {% elif otherthing %}
-        ...
-    {% elif foothing %}
-        ...
-    {% else %}
-        ...
-    {% endif %}
-
-Filter Arguments
-~~~~~~~~~~~~~~~~
-
-Jinja2 provides more than one argument for filters.  Also the syntax for
-argument passing is different.  A template that looks like this in Django::
-
-    {{ items|join:", " }}
-
-looks like this in Jinja2::
-
-    {{ items|join(', ') }}
-
-In fact it's a bit more verbose but it allows different types of arguments -
-including variables - and more than one of them.
-
-Tests
-~~~~~
-
-In addition to filters there also are tests you can perform using the is
-operator.  Here are some examples::
-
-    {% if user.user_id is odd %}
-        {{ user.username|e }} is odd
-    {% else %}
-        hmm. {{ user.username|e }} looks pretty normal
-    {% endif %}
-
-Loops
-~~~~~
-
-For loops work very similar to Django, the only incompatibility is that in
-Jinja2 the special variable for the loop context is called `loop` and not
-`forloop` like in Django.
-
-Cycle
-~~~~~
-
-The ``{% cycle %}`` tag does not exist in Jinja because of it's implicit
-nature.  However you can achieve mostly the same by using the `cycle`
-method on a loop object.
-
-The following Django template::
-
-    {% for user in users %}
-        <li class="{% cycle 'odd' 'even' %}">{{ user }}</li>
-    {% endfor %}
-
-Would look like this in Jinja::
-
-    {% for user in users %}
-        <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
-    {% endfor %}
-
-There is no equivalent of ``{% cycle ... as variable %}``.
-
-
-Mako
-----
-
-.. highlight:: html+mako
-
-If you have used Mako so far and want to switch to Jinja2 you can configure
-Jinja2 to look more like Mako:
-
-.. sourcecode:: python
-
-    env = Environment('<%', '%>', '${', '}', '%')
-
-Once the environment is configure like that Jinja2 should be able to interpret
-a small subset of Mako templates.  Jinja2 does not support embedded Python code
-so you would have to move that out of the template.  The syntax for defs (in
-Jinja2 defs are called macros) and template inheritance is different too.  The
-following Mako template::
-
-    <%inherit file="layout.html" />
-    <%def name="title()">Page Title</%def>
-    <ul>
-    % for item in list:
-        <li>${item}</li>
-    % endfor
-    </ul>
-
-Looks like this in Jinja2 with the above configuration::
-
-    <% extends "layout.html" %>
-    <% block title %>Page Title<% endblock %>
-    <% block body %>
-    <ul>
-    % for item in list:
-        <li>${item}</li>
-    % endfor
-    </ul>
-    <% endblock %>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst b/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst
deleted file mode 100644
index 4a1f6ff..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst
+++ /dev/null
@@ -1,1365 +0,0 @@
-Template Designer Documentation
-===============================
-
-.. highlight:: html+jinja
-
-This document describes the syntax and semantics of the template engine and
-will be most useful as reference to those creating Jinja templates.  As the
-template engine is very flexible the configuration from the application might
-be slightly different from here in terms of delimiters and behavior of
-undefined values.
-
-
-Synopsis
---------
-
-A template is simply a text file.  It can generate any text-based format
-(HTML, XML, CSV, LaTeX, etc.).  It doesn't have a specific extension,
-``.html`` or ``.xml`` are just fine.
-
-A template contains **variables** or **expressions**, which get replaced with
-values when the template is evaluated, and tags, which control the logic of
-the template.  The template syntax is heavily inspired by Django and Python.
-
-Below is a minimal template that illustrates a few basics.  We will cover
-the details later in that document::
-
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-    <html lang="en">
-    <head>
-        <title>My Webpage</title>
-    </head>
-    <body>
-        <ul id="navigation">
-        {% for item in navigation %}
-            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
-        {% endfor %}
-        </ul>
-
-        <h1>My Webpage</h1>
-        {{ a_variable }}
-    </body>
-    </html>
-
-This covers the default settings.  The application developer might have
-changed the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar.
-
-There are two kinds of delimiers. ``{% ... %}`` and ``{{ ... }}``.  The first
-one is used to execute statements such as for-loops or assign values, the
-latter prints the result of the expression to the template.
-
-.. _variables:
-
-Variables
----------
-
-The application passes variables to the templates you can mess around in the
-template.  Variables may have attributes or elements on them you can access
-too.  How a variable looks like, heavily depends on the application providing
-those.
-
-You can use a dot (``.``) to access attributes of a variable, alternative the
-so-called "subscript" syntax (``[]``) can be used.  The following lines do
-the same::
-
-    {{ foo.bar }}
-    {{ foo['bar'] }}
-
-It's important to know that the curly braces are *not* part of the variable
-but the print statement.  If you access variables inside tags don't put the
-braces around.
-
-If a variable or attribute does not exist you will get back an undefined
-value.  What you can do with that kind of value depends on the application
-configuration, the default behavior is that it evaluates to an empty string
-if printed and that you can iterate over it, but every other operation fails.
-
-.. _notes-on-subscriptions:
-
-.. admonition:: Implementation
-
-    For convenience sake ``foo.bar`` in Jinja2 does the following things on
-    the Python layer:
-
-    -   check if there is an attribute called `bar` on `foo`.
-    -   if there is not, check if there is an item ``'bar'`` in `foo`.
-    -   if there is not, return an undefined object.
-
-    ``foo['bar']`` on the other hand works mostly the same with the a small
-    difference in the order:
-
-    -   check if there is an item ``'bar'`` in `foo`.
-    -   if there is not, check if there is an attribute called `bar` on `foo`.
-    -   if there is not, return an undefined object.
-
-    This is important if an object has an item or attribute with the same
-    name.  Additionally there is the :func:`attr` filter that just looks up
-    attributes.
-
-.. _filters:
-
-Filters
--------
-
-Variables can by modified by **filters**.  Filters are separated from the
-variable by a pipe symbol (``|``) and may have optional arguments in
-parentheses.  Multiple filters can be chained.  The output of one filter is
-applied to the next.
-
-``{{ name|striptags|title }}`` for example will remove all HTML Tags from the
-`name` and title-cases it.  Filters that accept arguments have parentheses
-around the arguments, like a function call.  This example will join a list
-by commas:  ``{{ list|join(', ') }}``.
-
-The :ref:`builtin-filters` below describes all the builtin filters.
-
-.. _tests:
-
-Tests
------
-
-Beside filters there are also so called "tests" available.  Tests can be used
-to test a variable against a common expression.  To test a variable or
-expression you add `is` plus the name of the test after the variable.  For
-example to find out if a variable is defined you can do ``name is defined``
-which will then return true or false depending on if `name` is defined.
-
-Tests can accept arguments too.  If the test only takes one argument you can
-leave out the parentheses to group them.  For example the following two
-expressions do the same::
-
-    {% if loop.index is divisibleby 3 %}
-    {% if loop.index is divisibleby(3) %}
-
-The :ref:`builtin-tests` below describes all the builtin tests.
-
-
-Comments
---------
-
-To comment-out part of a line in a template, use the comment syntax which is
-by default set to ``{# ... #}``.  This is useful to comment out parts of the
-template for debugging or to add information for other template designers or
-yourself::
-
-    {# note: disabled template because we no longer use this
-        {% for user in users %}
-            ...
-        {% endfor %}
-    #}
-
-
-Whitespace Control
-------------------
-
-In the default configuration whitespace is not further modified by the
-template engine, so each whitespace (spaces, tabs, newlines etc.) is returned
-unchanged.  If the application configures Jinja to `trim_blocks` the first
-newline after a a template tag is removed automatically (like in PHP).
-
-But you can also strip whitespace in templates by hand.  If you put an minus
-sign (``-``) to the start or end of an block (for example a for tag), a
-comment or variable expression you can remove the whitespaces after or before
-that block::
-
-    {% for item in seq -%}
-        {{ item }}
-    {%- endfor %}
-    
-This will yield all elements without whitespace between them.  If `seq` was
-a list of numbers from ``1`` to ``9`` the output would be ``123456789``.
-
-If :ref:`line-statements` are enabled they strip leading whitespace
-automatically up to the beginning of the line.
-
-.. admonition:: Note
-
-    You must not use a whitespace between the tag and the minus sign.
-
-    **valid**::
-
-        {%- if foo -%}...{% endif %}
-
-    **invalid**::
-
-        {% - if foo - %}...{% endif %}
-
-
-Escaping
---------
-
-It is sometimes desirable or even necessary to have Jinja ignore parts it
-would otherwise handle as variables or blocks.  For example if the default
-syntax is used and you want to use ``{{`` as raw string in the template and
-not start a variable you have to use a trick.
-
-The easiest way is to output the variable delimiter (``{{``) by using a
-variable expression::
-
-    {{ '{{' }}
-
-For bigger sections it makes sense to mark a block `raw`.  For example to
-put Jinja syntax as example into a template you can use this snippet::
-
-    {% raw %}
-        <ul>
-        {% for item in seq %}
-            <li>{{ item }}</li>
-        {% endfor %}
-        </ul>
-    {% endraw %}
-
-
-.. _line-statements:
-
-Line Statements
----------------
-
-If line statements are enabled by the application it's possible to mark a
-line as a statement.  For example if the line statement prefix is configured
-to ``#`` the following two examples are equivalent::
-
-    <ul>
-    # for item in seq
-        <li>{{ item }}</li>
-    # endfor
-    </ul>
-
-    <ul>
-    {% for item in seq %}
-        <li>{{ item }}</li>
-    {% endfor %}
-    </ul>
-
-The line statement prefix can appear anywhere on the line as long as no text
-precedes it.  For better readability statements that start a block (such as
-`for`, `if`, `elif` etc.) may end with a colon::
-
-    # for item in seq:
-        ...
-    # endfor
-
-
-.. admonition:: Note
-
-    Line statements can span multiple lines if there are open parentheses,
-    braces or brackets::
-
-        <ul>
-        # for href, caption in [('index.html', 'Index'),
-                                ('about.html', 'About')]:
-            <li><a href="{{ href }}">{{ caption }}</a></li>
-        # endfor
-        </ul>
-
-Since Jinja 2.2 line-based comments are available as well.  For example if
-the line-comment prefix is configured to be ``##`` everything from ``##`` to
-the end of the line is ignored (excluding the newline sign)::
-
-    # for item in seq:
-        <li>{{ item }}</li>     ## this comment is ignored
-    # endfor
-
-
-.. _template-inheritance:
-
-Template Inheritance
---------------------
-
-The most powerful part of Jinja is template inheritance. Template inheritance
-allows you to build a base "skeleton" template that contains all the common
-elements of your site and defines **blocks** that child templates can override.
-
-Sounds complicated but is very basic. It's easiest to understand it by starting
-with an example.
-
-
-Base Template
-~~~~~~~~~~~~~
-
-This template, which we'll call ``base.html``, defines a simple HTML skeleton
-document that you might use for a simple two-column page. It's the job of
-"child" templates to fill the empty blocks with content::
-
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-    <html lang="en">
-    <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        {% block head %}
-        <link rel="stylesheet" href="style.css" />
-        <title>{% block title %}{% endblock %} - My Webpage</title>
-        {% endblock %}
-    </head>
-    <body>
-        <div id="content">{% block content %}{% endblock %}</div>
-        <div id="footer">
-            {% block footer %}
-            &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
-            {% endblock %}
-        </div>
-    </body>
-
-In this example, the ``{% block %}`` tags define four blocks that child templates
-can fill in. All the `block` tag does is to tell the template engine that a
-child template may override those portions of the template.
-
-Child Template
-~~~~~~~~~~~~~~
-
-A child template might look like this::
-
-    {% extends "base.html" %}
-    {% block title %}Index{% endblock %}
-    {% block head %}
-        {{ super() }}
-        <style type="text/css">
-            .important { color: #336699; }
-        </style>
-    {% endblock %}
-    {% block content %}
-        <h1>Index</h1>
-        <p class="important">
-          Welcome on my awesome homepage.
-        </p>
-    {% endblock %}
-
-The ``{% extends %}`` tag is the key here. It tells the template engine that
-this template "extends" another template.  When the template system evaluates
-this template, first it locates the parent.  The extends tag should be the
-first tag in the template.  Everything before it is printed out normally and
-may cause confusion.  For details about this behavior and how to take
-advantage of it, see :ref:`null-master-fallback`.
-
-The filename of the template depends on the template loader.  For example the
-:class:`FileSystemLoader` allows you to access other templates by giving the
-filename.  You can access templates in subdirectories with an slash::
-
-    {% extends "layout/default.html" %}
-
-But this behavior can depend on the application embedding Jinja.  Note that
-since the child template doesn't define the ``footer`` block, the value from
-the parent template is used instead.
-
-You can't define multiple ``{% block %}`` tags with the same name in the
-same template.  This limitation exists because a block tag works in "both"
-directions.  That is, a block tag doesn't just provide a hole to fill - it
-also defines the content that fills the hole in the *parent*.  If there
-were two similarly-named ``{% block %}`` tags in a template, that template's
-parent wouldn't know which one of the blocks' content to use.
-
-If you want to print a block multiple times you can however use the special
-`self` variable and call the block with that name::
-
-    <title>{% block title %}{% endblock %}</title>
-    <h1>{{ self.title() }}</h1>
-    {% block body %}{% endblock %}
-
-
-Super Blocks
-~~~~~~~~~~~~
-
-It's possible to render the contents of the parent block by calling `super`.
-This gives back the results of the parent block::
-
-    {% block sidebar %}
-        <h3>Table Of Contents</h3>
-        ...
-        {{ super() }}
-    {% endblock %}
-
-
-Named Block End-Tags
-~~~~~~~~~~~~~~~~~~~~
-
-Jinja2 allows you to put the name of the block after the end tag for better
-readability::
-
-    {% block sidebar %}
-        {% block inner_sidebar %}
-            ...
-        {% endblock inner_sidebar %}
-    {% endblock sidebar %}
-
-However the name after the `endblock` word must match the block name.
-
-
-Block Nesting and Scope
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Blocks can be nested for more complex layouts.  However per default blocks
-may not access variables from outer scopes::
-
-    {% for item in seq %}
-        <li>{% block loop_item %}{{ item }}{% endblock %}</li>
-    {% endfor %}
-
-This example would output empty ``<li>`` items because `item` is unavailable
-inside the block.  The reason for this is that if the block is replaced by
-a child template a variable would appear that was not defined in the block or
-passed to the context.
-
-Starting with Jinja 2.2 you can explicitly specify that variables are
-available in a block by setting the block to "scoped" by adding the `scoped`
-modifier to a block declaration::
-
-    {% for item in seq %}
-        <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
-    {% endfor %}
-
-When overriding a block the `scoped` modifier does not have to be provided.
-
-
-Template Objects
-~~~~~~~~~~~~~~~~
-
-.. versionchanged:: 2.4
-
-If a template object was passed to the template context you can
-extend from that object as well.  Assuming the calling code passes
-a layout template as `layout_template` to the environment, this
-code works::
-
-    {% extends layout_template %}
-
-Previously the `layout_template` variable had to be a string with
-the layout template's filename for this to work.
-
-
-HTML Escaping
--------------
-
-When generating HTML from templates, there's always a risk that a variable will
-include characters that affect the resulting HTML.  There are two approaches:
-manually escaping each variable or automatically escaping everything by default.
-
-Jinja supports both, but what is used depends on the application configuration.
-The default configuaration is no automatic escaping for various reasons:
-
--   escaping everything except of safe values will also mean that Jinja is
-    escaping variables known to not include HTML such as numbers which is
-    a huge performance hit.
-
--   The information about the safety of a variable is very fragile.  It could
-    happen that by coercing safe and unsafe values the return value is double
-    escaped HTML.
-
-Working with Manual Escaping
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If manual escaping is enabled it's **your** responsibility to escape
-variables if needed.  What to escape?  If you have a variable that *may*
-include any of the following chars (``>``, ``<``, ``&``, or ``"``) you
-**have to** escape it unless the variable contains well-formed and trusted
-HTML.  Escaping works by piping the variable through the ``|e`` filter:
-``{{ user.username|e }}``.
-
-Working with Automatic Escaping
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When automatic escaping is enabled everything is escaped by default except
-for values explicitly marked as safe.  Those can either be marked by the
-application or in the template by using the `|safe` filter.  The main
-problem with this approach is that Python itself doesn't have the concept
-of tainted values so the information if a value is safe or unsafe can get
-lost.  If the information is lost escaping will take place which means that
-you could end up with double escaped contents.
-
-Double escaping is easy to avoid however, just rely on the tools Jinja2
-provides and don't use builtin Python constructs such as the string modulo
-operator.
-
-Functions returning template data (macros, `super`, `self.BLOCKNAME`) return
-safe markup always.
-
-String literals in templates with automatic escaping are considered unsafe
-too.  The reason for this is that the safe string is an extension to Python
-and not every library will work properly with it.
-
-
-List of Control Structures
---------------------------
-
-A control structure refers to all those things that control the flow of a
-program - conditionals (i.e. if/elif/else), for-loops, as well as things like
-macros and blocks.  Control structures appear inside ``{% ... %}`` blocks
-in the default syntax.
-
-For
-~~~
-
-Loop over each item in a sequence.  For example, to display a list of users
-provided in a variable called `users`::
-
-    <h1>Members</h1>
-    <ul>
-    {% for user in users %}
-      <li>{{ user.username|e }}</li>
-    {% endfor %}
-    </ul>
-
-Inside of a for loop block you can access some special variables:
-
-+-----------------------+---------------------------------------------------+
-| Variable              | Description                                       |
-+=======================+===================================================+
-| `loop.index`          | The current iteration of the loop. (1 indexed)    |
-+-----------------------+---------------------------------------------------+
-| `loop.index0`         | The current iteration of the loop. (0 indexed)    |
-+-----------------------+---------------------------------------------------+
-| `loop.revindex`       | The number of iterations from the end of the loop |
-|                       | (1 indexed)                                       |
-+-----------------------+---------------------------------------------------+
-| `loop.revindex0`      | The number of iterations from the end of the loop |
-|                       | (0 indexed)                                       |
-+-----------------------+---------------------------------------------------+
-| `loop.first`          | True if first iteration.                          |
-+-----------------------+---------------------------------------------------+
-| `loop.last`           | True if last iteration.                           |
-+-----------------------+---------------------------------------------------+
-| `loop.length`         | The number of items in the sequence.              |
-+-----------------------+---------------------------------------------------+
-| `loop.cycle`          | A helper function to cycle between a list of      |
-|                       | sequences.  See the explanation below.            |
-+-----------------------+---------------------------------------------------+
-
-Within a for-loop, it's possible to cycle among a list of strings/variables
-each time through the loop by using the special `loop.cycle` helper::
-
-    {% for row in rows %}
-        <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
-    {% endfor %}
-
-With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound
-cycling.  For more information have a look at the :ref:`builtin-globals`.
-
-.. _loop-filtering:
-
-Unlike in Python it's not possible to `break` or `continue` in a loop.  You
-can however filter the sequence during iteration which allows you to skip
-items.  The following example skips all the users which are hidden::
-
-    {% for user in users if not user.hidden %}
-        <li>{{ user.username|e }}</li>
-    {% endfor %}
-
-The advantage is that the special `loop` variable will count correctly thus
-not counting the users not iterated over.
-
-If no iteration took place because the sequence was empty or the filtering
-removed all the items from the sequence you can render a replacement block
-by using `else`::
-
-    <ul>
-    {% for user in users %}
-        <li>{{ user.username|e }}</li>
-    {% else %}
-        <li><em>no users found</em></li>
-    {% endfor %}
-    </ul>
-
-It is also possible to use loops recursively.  This is useful if you are
-dealing with recursive data such as sitemaps.  To use loops recursively you
-basically have to add the `recursive` modifier to the loop definition and
-call the `loop` variable with the new iterable where you want to recurse.
-
-The following example implements a sitemap with recursive loops::
-
-    <ul class="sitemap">
-    {%- for item in sitemap recursive %}
-        <li><a href="{{ item.href|e }}">{{ item.title }}</a>
-        {%- if item.children -%}
-            <ul class="submenu">{{ loop(item.children) }}</ul>
-        {%- endif %}</li>
-    {%- endfor %}
-    </ul>
-
-
-If
-~~
-
-The `if` statement in Jinja is comparable with the if statements of Python.
-In the simplest form you can use it to test if a variable is defined, not
-empty or not false::
-
-    {% if users %}
-    <ul>
-    {% for user in users %}
-        <li>{{ user.username|e }}</li>
-    {% endfor %}
-    </ul>
-    {% endif %}
-
-For multiple branches `elif` and `else` can be used like in Python.  You can
-use more complex :ref:`expressions` there too::
-
-    {% if kenny.sick %}
-        Kenny is sick.
-    {% elif kenny.dead %}
-        You killed Kenny!  You bastard!!!
-    {% else %}
-        Kenny looks okay --- so far
-    {% endif %}
-
-If can also be used as :ref:`inline expression <if-expression>` and for
-:ref:`loop filtering <loop-filtering>`.
-
-
-Macros
-~~~~~~
-
-Macros are comparable with functions in regular programming languages.  They
-are useful to put often used idioms into reusable functions to not repeat
-yourself.
-
-Here a small example of a macro that renders a form element::
-
-    {% macro input(name, value='', type='text', size=20) -%}
-        <input type="{{ type }}" name="{{ name }}" value="{{
-            value|e }}" size="{{ size }}">
-    {%- endmacro %}
-
-The macro can then be called like a function in the namespace::
-
-    <p>{{ input('username') }}</p>
-    <p>{{ input('password', type='password') }}</p>
-
-If the macro was defined in a different template you have to
-:ref:`import <import>` it first.
-
-Inside macros you have access to three special variables:
-
-`varargs`
-    If more positional arguments are passed to the macro than accepted by the
-    macro they end up in the special `varargs` variable as list of values.
-
-`kwargs`
-    Like `varargs` but for keyword arguments.  All unconsumed keyword
-    arguments are stored in this special variable.
-
-`caller`
-    If the macro was called from a :ref:`call<call>` tag the caller is stored
-    in this variable as macro which can be called.
-
-Macros also expose some of their internal details.  The following attributes
-are available on a macro object:
-
-`name`
-    The name of the macro.  ``{{ input.name }}`` will print ``input``.
-
-`arguments`
-    A tuple of the names of arguments the macro accepts.
-
-`defaults`
-    A tuple of default values.
-
-`catch_kwargs`
-    This is `true` if the macro accepts extra keyword arguments (ie: accesses
-    the special `kwargs` variable).
-
-`catch_varargs`
-    This is `true` if the macro accepts extra positional arguments (ie:
-    accesses the special `varargs` variable).
-
-`caller`
-    This is `true` if the macro accesses the special `caller` variable and may
-    be called from a :ref:`call<call>` tag.
-
-If a macro name starts with an underscore it's not exported and can't
-be imported.
-
-
-.. _call:
-
-Call
-~~~~
-
-In some cases it can be useful to pass a macro to another macro.  For this
-purpose you can use the special `call` block.  The following example shows
-a macro that takes advantage of the call functionality and how it can be
-used::
-
-    {% macro render_dialog(title, class='dialog') -%}
-        <div class="{{ class }}">
-            <h2>{{ title }}</h2>
-            <div class="contents">
-                {{ caller() }}
-            </div>
-        </div>
-    {%- endmacro %}
-
-    {% call render_dialog('Hello World') %}
-        This is a simple dialog rendered by using a macro and
-        a call block.
-    {% endcall %}
-
-It's also possible to pass arguments back to the call block.  This makes it
-useful as replacement for loops.  Generally speaking a call block works
-exactly like an macro, just that it doesn't have a name.
-
-Here an example of how a call block can be used with arguments::
-
-    {% macro dump_users(users) -%}
-        <ul>
-        {%- for user in users %}
-            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
-        {%- endfor %}
-        </ul>
-    {%- endmacro %}
-
-    {% call(user) dump_users(list_of_user) %}
-        <dl>
-            <dl>Realname</dl>
-            <dd>{{ user.realname|e }}</dd>
-            <dl>Description</dl>
-            <dd>{{ user.description }}</dd>
-        </dl>
-    {% endcall %}
-
-
-Filters
-~~~~~~~
-
-Filter sections allow you to apply regular Jinja2 filters on a block of
-template data.  Just wrap the code in the special `filter` section::
-
-    {% filter upper %}
-        This text becomes uppercase
-    {% endfilter %}
-
-
-Assignments
-~~~~~~~~~~~
-
-Inside code blocks you can also assign values to variables.  Assignments at
-top level (outside of blocks, macros or loops) are exported from the template
-like top level macros and can be imported by other templates.
-
-Assignments use the `set` tag and can have multiple targets::
-
-    {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
-    {% set key, value = call_something() %}
-
-
-Extends
-~~~~~~~
-
-The `extends` tag can be used to extend a template from another one.  You
-can have multiple of them in a file but only one of them may be executed
-at the time.  See the section about :ref:`template-inheritance` above.
-
-
-Block
-~~~~~
-
-Blocks are used for inheritance and act as placeholders and replacements
-at the same time.  They are documented in detail as part of the section
-about :ref:`template-inheritance`.
-
-
-Include
-~~~~~~~
-
-The `include` statement is useful to include a template and return the
-rendered contents of that file into the current namespace::
-
-    {% include 'header.html' %}
-        Body
-    {% include 'footer.html' %}
-
-Included templates have access to the variables of the active context by
-default.  For more details about context behavior of imports and includes
-see :ref:`import-visibility`.
-
-From Jinja 2.2 onwards you can mark an include with ``ignore missing`` in
-which case Jinja will ignore the statement if the template to be ignored
-does not exist.  When combined with ``with`` or ``without context`` it has
-to be placed *before* the context visibility statement.  Here some valid
-examples::
-
-    {% include "sidebar.html" ignore missing %}
-    {% include "sidebar.html" ignore missing with context %}
-    {% include "sidebar.html" ignore missing without context %}
-
-.. versionadded:: 2.2
-
-You can also provide a list of templates that are checked for existence
-before inclusion.  The first template that exists will be included.  If
-`ignore missing` is given, it will fall back to rendering nothing if
-none of the templates exist, otherwise it will raise an exception.
-
-Example::
-
-    {% include ['page_detailed.html', 'page.html'] %}
-    {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
-
-.. versionchanged:: 2.4
-   If a template object was passed to the template context you can
-   include that object using `include`.
-
-.. _import:
-
-Import
-~~~~~~
-
-Jinja2 supports putting often used code into macros.  These macros can go into
-different templates and get imported from there.  This works similar to the
-import statements in Python.  It's important to know that imports are cached
-and imported templates don't have access to the current template variables,
-just the globals by defualt.  For more details about context behavior of
-imports and includes see :ref:`import-visibility`.
-
-There are two ways to import templates.  You can import the complete template
-into a variable or request specific macros / exported variables from it.
-
-Imagine we have a helper module that renders forms (called `forms.html`)::
-
-    {% macro input(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 %}
-
-The easiest and most flexible is importing the whole module into a variable.
-That way you can access the attributes::
-
-    {% import 'forms.html' as forms %}
-    <dl>
-        <dt>Username</dt>
-        <dd>{{ forms.input('username') }}</dd>
-        <dt>Password</dt>
-        <dd>{{ forms.input('password', type='password') }}</dd>
-    </dl>
-    <p>{{ forms.textarea('comment') }}</p>
-
-
-Alternatively you can import names from the template into the current
-namespace::
-
-    {% from 'forms.html' import input as input_field, textarea %}
-    <dl>
-        <dt>Username</dt>
-        <dd>{{ input_field('username') }}</dd>
-        <dt>Password</dt>
-        <dd>{{ input_field('password', type='password') }}</dd>
-    </dl>
-    <p>{{ textarea('comment') }}</p>
-
-Macros and variables starting with one ore more underscores are private and
-cannot be imported.
-
-.. versionchanged:: 2.4
-   If a template object was passed to the template context you can
-   import from that object.
-
-
-.. _import-visibility:
-
-Import Context Behavior
------------------------
-
-Per default included templates are passed the current context and imported
-templates not.  The reason for this is that imports unlike includes are
-cached as imports are often used just as a module that holds macros.
-
-This however can be changed of course explicitly.  By adding `with context`
-or `without context` to the import/include directive the current context
-can be passed to the template and caching is disabled automatically.
-
-Here two examples::
-
-    {% from 'forms.html' import input with context %}
-    {% include 'header.html' without context %}
-
-.. admonition:: Note
-
-    In Jinja 2.0 the context that was passed to the included template
-    did not include variables defined in the template.  As a matter of
-    fact this did not work::
-
-        {% for box in boxes %}
-            {% include "render_box.html" %}
-        {% endfor %}
-
-    The included template ``render_box.html`` is not able to access
-    `box` in Jinja 2.0, but in Jinja 2.1.
-
-
-.. _expressions:
-
-Expressions
------------
-
-Jinja allows basic expressions everywhere.  These work very similar to regular
-Python and even if you're not working with Python you should feel comfortable
-with it.
-
-Literals
-~~~~~~~~
-
-The simplest form of expressions are literals.  Literals are representations
-for Python objects such as strings and numbers.  The following literals exist:
-
-"Hello World":
-    Everything between two double or single quotes is a string.  They are
-    useful whenever you need a string in the template (for example as
-    arguments to function calls, filters or just to extend or include a
-    template).
-
-42 / 42.23:
-    Integers and floating point numbers are created by just writing the
-    number down.  If a dot is present the number is a float, otherwise an
-    integer.  Keep in mind that for Python ``42`` and ``42.0`` is something
-    different.
-
-['list', 'of', 'objects']:
-    Everything between two brackets is a list.  Lists are useful to store
-    sequential data in or to iterate over them.  For example you can easily
-    create a list of links using lists and tuples with a for loop::
-
-        <ul>
-        {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
-                                 ('downloads.html', 'Downloads')] %}
-            <li><a href="{{ href }}">{{ caption }}</a></li>
-        {% endfor %}
-        </ul>
-
-('tuple', 'of', 'values'):
-    Tuples are like lists, just that you can't modify them.  If the tuple
-    only has one item you have to end it with a comma.  Tuples are usually
-    used to represent items of two or more elements.  See the example above
-    for more details.
-
-{'dict': 'of', 'key': 'and', 'value': 'pairs'}:
-    A dict in Python is a structure that combines keys and values.  Keys must
-    be unique and always have exactly one value.  Dicts are rarely used in
-    templates, they are useful in some rare cases such as the :func:`xmlattr`
-    filter.
-
-true / false:
-    true is always true and false is always false.
-
-.. admonition:: Note
-
-    The special constants `true`, `false` and `none` are indeed lowercase.
-    Because that caused confusion in the past, when writing `True` expands
-    to an undefined variable that is considered false, all three of them can
-    be written in title case too (`True`, `False`, and `None`).  However for
-    consistency (all Jinja identifiers are lowercase) you should use the
-    lowercase versions.
-
-Math
-~~~~
-
-Jinja allows you to calculate with values.  This is rarely useful in templates
-but exists for completeness' sake.  The following operators are supported:
-
-\+
-    Adds two objects together.  Usually the objects are numbers but if both are
-    strings or lists you can concatenate them this way.  This however is not
-    the preferred way to concatenate strings!  For string concatenation have
-    a look at the ``~`` operator.  ``{{ 1 + 1 }}`` is ``2``.
-
-\-
-    Substract the second number from the first one.  ``{{ 3 - 2 }}`` is ``1``.
-
-/
-    Divide two numbers.  The return value will be a floating point number.
-    ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
-
-//
-    Divide two numbers and return the truncated integer result.
-    ``{{ 20 / 7 }}`` is ``2``.
-
-%
-    Calculate the remainder of an integer division.  ``{{ 11 % 7 }}`` is ``4``.
-
-\*
-    Multiply the left operand with the right one.  ``{{ 2 * 2 }}`` would
-    return ``4``.  This can also be used to repeat a string multiple times.
-    ``{{ '=' * 80 }}`` would print a bar of 80 equal signs.
-
-\**
-    Raise the left operand to the power of the right operand.  ``{{ 2**3 }}``
-    would return ``8``.
-
-Comparisons
-~~~~~~~~~~~
-
-==
-    Compares two objects for equality.
-
-!=
-    Compares two objects for inequality.
-
->
-    `true` if the left hand side is greater than the right hand side.
-
->=
-    `true` if the left hand side is greater or equal to the right hand side.
-
-<
-    `true` if the left hand side is lower than the right hand side.
-
-<=
-    `true` if the left hand side is lower or equal to the right hand side.
-
-Logic
-~~~~~
-
-For `if` statements, `for` filtering or `if` expressions it can be useful to
-combine multiple expressions:
-
-and
-    Return true if the left and the right operand is true.
-
-or
-    Return true if the left or the right operand is true.
-
-not
-    negate a statement (see below).
-
-(expr)
-    group an expression.
-
-.. admonition:: Note
-
-    The ``is`` and ``in`` operators support negation using an infix notation
-    too: ``foo is not bar`` and ``foo not in bar`` instead of ``not foo is bar``
-    and ``not foo in bar``.  All other expressions require a prefix notation:
-    ``not (foo and bar).``
-
-
-Other Operators
-~~~~~~~~~~~~~~~
-
-The following operators are very useful but don't fit into any of the other
-two categories:
-
-in
-    Perform sequence / mapping containment test.  Returns true if the left
-    operand is contained in the right.  ``{{ 1 in [1, 2, 3] }}`` would for
-    example return true.
-
-is
-    Performs a :ref:`test <tests>`.
-
-\|
-    Applies a :ref:`filter <filters>`.
-
-~
-    Converts all operands into strings and concatenates them.
-    ``{{ "Hello " ~ name ~ "!" }}`` would return (assuming `name` is
-    ``'John'``) ``Hello John!``.
-
-()
-    Call a callable: ``{{ post.render() }}``.  Inside of the parentheses you
-    can use positional arguments and keyword arguments like in python:
-    ``{{ post.render(user, full=true) }}``.
-
-. / []
-    Get an attribute of an object.  (See :ref:`variables`)
-
-
-.. _if-expression:
-
-If Expression
-~~~~~~~~~~~~~
-
-It is also possible to use inline `if` expressions.  These are useful in some
-situations.  For example you can use this to extend from one template if a
-variable is defined, otherwise from the default layout template::
-
-    {% extends layout_template if layout_template is defined else 'master.html' %}
-
-The general syntax is ``<do something> if <something is true> else <do
-something else>``.
-
-The `else` part is optional.  If not provided the else block implicitly
-evaluates into an undefined object::
-
-    {{ '[%s]' % page.title if page.title }}
-
-
-.. _builtin-filters:
-
-List of Builtin Filters
------------------------
-
-.. jinjafilters::
-
-
-.. _builtin-tests:
-
-List of Builtin Tests
----------------------
-
-.. jinjatests::
-
-.. _builtin-globals:
-
-List of Global Functions
-------------------------
-
-The following functions are available in the global scope by default:
-
-.. function:: range([start,] stop[, step])
-
-    Return a list containing an arithmetic progression of integers.
-    range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
-    When step is given, it specifies the increment (or decrement).
-    For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
-    These are exactly the valid indices for a list of 4 elements.
-
-    This is useful to repeat a template block multiple times for example
-    to fill a list.  Imagine you have 7 users in the list but you want to
-    render three empty items to enforce a height with CSS::
-
-        <ul>
-        {% for user in users %}
-            <li>{{ user.username }}</li>
-        {% endfor %}
-        {% for number in range(10 - users|count) %}
-            <li class="empty"><span>...</span></li>
-        {% endfor %}
-        </ul>
-
-.. function:: lipsum(n=5, html=True, min=20, max=100)
-
-    Generates some lorem ipsum for the template.  Per default five paragraphs
-    with HTML are generated each paragraph between 20 and 100 words.  If html
-    is disabled regular text is returned.  This is useful to generate simple
-    contents for layout testing.
-
-.. function:: dict(\**items)
-
-    A convenient alternative to dict literals.  ``{'foo': 'bar'}`` is the same
-    as ``dict(foo='bar')``.
-
-.. class:: cycler(\*items)
-
-    The cycler allows you to cycle among values similar to how `loop.cycle`
-    works.  Unlike `loop.cycle` however you can use this cycler outside of
-    loops or over multiple loops.
-
-    This is for example very useful if you want to show a list of folders and
-    files, with the folders on top, but both in the same list with alternating
-    row colors.
-
-    The following example shows how `cycler` can be used::
-
-        {% set row_class = cycler('odd', 'even') %}
-        <ul class="browser">
-        {% for folder in folders %}
-          <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
-        {% endfor %}
-        {% for filename in files %}
-          <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
-        {% endfor %}
-        </ul>
-
-    A cycler has the following attributes and methods:
-
-    .. method:: reset()
-
-        Resets the cycle to the first item.
-
-    .. method:: next()
-
-        Goes one item a head and returns the then current item.
-
-    .. attribute:: current
-
-        Returns the current item.
-    
-    **new in Jinja 2.1**
-
-.. class:: joiner(sep=', ')
-
-    A tiny helper that can be use to "join" multiple sections.  A joiner is
-    passed a string and will return that string every time it's calld, except
-    the first time in which situation it returns an empty string.  You can
-    use this to join things::
-
-        {% set pipe = joiner("|") %}
-        {% if categories %} {{ pipe() }}
-            Categories: {{ categories|join(", ") }}
-        {% endif %}
-        {% if author %} {{ pipe() }}
-            Author: {{ author() }}
-        {% endif %}
-        {% if can_edit %} {{ pipe() }}
-            <a href="?action=edit">Edit</a>
-        {% endif %}
-
-    **new in Jinja 2.1**
-
-
-Extensions
-----------
-
-The following sections cover the built-in Jinja2 extensions that may be
-enabled by the application.  The application could also provide further
-extensions not covered by this documentation.  In that case there should
-be a separate document explaining the extensions.
-
-.. _i18n-in-templates:
-
-i18n
-~~~~
-
-If the i18n extension is enabled it's possible to mark parts in the template
-as translatable.  To mark a section as translatable you can use `trans`::
-
-    <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
-
-To translate a template expression --- say, using template filters or just
-accessing an attribute of an object --- you need to bind the expression to a
-name for use within the translation block::
-
-    <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
-
-If you need to bind more than one expression inside a `trans` tag, separate
-the pieces with a comma (``,``)::
-
-    {% trans book_title=book.title, author=author.name %}
-    This is {{ book_title }} by {{ author }}
-    {% endtrans %}
-
-Inside trans tags no statements are allowed, only variable tags are.
-
-To pluralize, specify both the singular and plural forms with the `pluralize`
-tag, which appears between `trans` and `endtrans`::
-
-    {% trans count=list|length %}
-    There is {{ count }} {{ name }} object.
-    {% pluralize %}
-    There are {{ count }} {{ name }} objects.
-    {% endtrans %}
-
-Per default the first variable in a block is used to determine the correct
-singular or plural form.  If that doesn't work out you can specify the name
-which should be used for pluralizing by adding it as parameter to `pluralize`::
-
-    {% trans ..., user_count=users|length %}...
-    {% pluralize user_count %}...{% endtrans %}
-
-It's also possible to translate strings in expressions.  For that purpose
-three functions exist:
-
-_   `gettext`: translate a single string
--   `ngettext`: translate a pluralizable string
--   `_`: alias for `gettext`
-
-For example you can print a translated string easily this way::
-
-    {{ _('Hello World!') }}
-
-To use placeholders you can use the `format` filter::
-
-    {{ _('Hello %(user)s!')|format(user=user.username) }}
-
-For multiple placeholders always use keyword arguments to `format` as other
-languages may not use the words in the same order.
-
-.. versionchanged:: 2.5
-
-If newstyle gettext calls are activated (:ref:`newstyle-gettext`), using
-placeholders is a lot easier:
-
-.. sourcecode:: html+jinja
-
-    {{ gettext('Hello World!') }}
-    {{ gettext('Hello %(name)s!', name='World') }}
-    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
-
-Note that the `ngettext` function's format string automatically recieves
-the count as `num` parameter additionally to the regular parameters.
-
-
-Expression Statement
-~~~~~~~~~~~~~~~~~~~~
-
-If the expression-statement extension is loaded a tag called `do` is available
-that works exactly like the regular variable expression (``{{ ... }}``) just
-that it doesn't print anything.  This can be used to modify lists::
-
-    {% do navigation.append('a string') %}
-
-
-Loop Controls
-~~~~~~~~~~~~~
-
-If the application enables the :ref:`loopcontrols-extension` it's possible to
-use `break` and `continue` in loops.  When `break` is reached, the loop is
-terminated, if `continue` is eached the processing is stopped and continues
-with the next iteration.
-
-Here a loop that skips every second item::
-
-    {% for user in users %}
-        {%- if loop.index is even %}{% continue %}{% endif %}
-        ...
-    {% endfor %}
-
-Likewise a look that stops processing after the 10th iteration::
-
-    {% for user in users %}
-        {%- if loop.index >= 10 %}{% break %}{% endif %}
-    {%- endfor %}
-
-
-With Statement
-~~~~~~~~~~~~~~
-
-.. versionadded:: 2.3
-
-If the application enables the :ref:`with-extension` it is possible to
-use the `with` keyword in templates.  This makes it possible to create
-a new inner scope.  Variables set within this scope are not visible
-outside of the scope.
-
-With in a nutshell::
-
-    {% with %}
-        {% set foo = 42 %}
-        {{ foo }}           foo is 42 here
-    {% endwith %}
-    foo is not visible here any longer
-
-Because it is common to set variables at the beginning of the scope
-you can do that within the with statement.  The following two examples
-are equivalent::
-
-    {% with foo = 42 %}
-        {{ foo }}
-    {% endwith %}
-
-    {% with %}
-        {% set foo = 42 %}
-        {{ foo }}
-    {% endwith %}
-
-.. _autoescape-overrides:
-
-Autoescape Extension
---------------------
-
-.. versionadded:: 2.4
-
-If the application enables the :ref:`autoescape-extension` one can
-activate and deactivate the autoescaping from within the templates.
-
-Example::
-
-    {% autoescape true %}
-        Autoescaping is active within this block
-    {% endautoescape %}
-
-    {% autoescape false %}
-        Autoescaping is inactive within this block
-    {% endautoescape %}
-
-After the `endautoescape` the behavior is reverted to what it was before.

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst b/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst
deleted file mode 100644
index 566575e..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst
+++ /dev/null
@@ -1,100 +0,0 @@
-Tips and Tricks
-===============
-
-.. highlight:: html+jinja
-
-This part of the documentation shows some tips and tricks for Jinja2
-templates.
-
-
-.. _null-master-fallback:
-
-Null-Master Fallback
---------------------
-
-Jinja2 supports dynamic inheritance and does not distinguish between parent
-and child template as long as no `extends` tag is visited.  While this leads
-to the surprising behavior that everything before the first `extends` tag
-including whitespace is printed out instead of being igored, it can be used
-for a neat trick.
-
-Usually child templates extend from one template that adds a basic HTML
-skeleton.  However it's possible put the `extends` tag into an `if` tag to
-only extend from the layout template if the `standalone` variable evaluates
-to false which it does per default if it's not defined.  Additionally a very
-basic skeleton is added to the file so that if it's indeed rendered with
-`standalone` set to `True` a very basic HTML skeleton is added::
-
-    {% if not standalone %}{% extends 'master.html' %}{% endif -%}
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-    <title>{% block title %}The Page Title{% endblock %}</title>
-    <link rel="stylesheet" href="style.css" type="text/css">
-    {% block body %}
-      <p>This is the page body.</p>
-    {% endblock %}
-
-
-Alternating Rows
-----------------
-
-If you want to have different styles for each row of a table or
-list you can use the `cycle` method on the `loop` object::
-
-    <ul>
-    {% for row in rows %}
-      <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
-    {% endfor %}
-    </ul>
-
-`cycle` can take an unlimited amount of strings.  Each time this
-tag is encountered the next item from the list is rendered.
-
-
-Highlighting Active Menu Items
-------------------------------
-
-Often you want to have a navigation bar with an active navigation
-item.  This is really simple to achieve.  Because assignments outside
-of `block`\s in child templates are global and executed before the layout
-template is evaluated it's possible to define the active menu item in the
-child template::
-
-    {% extends "layout.html" %}
-    {% set active_page = "index" %}
-
-The layout template can then access `active_page`.  Additionally it makes
-sense to defined a default for that variable::
-
-    {% set navigation_bar = [
-        ('/', 'index', 'Index'),
-        ('/downloads/', 'downloads', 'Downloads'),
-        ('/about/', 'about', 'About')
-    ] -%}
-    {% set active_page = active_page|default('index') -%}
-    ...
-    <ul id="navigation">
-    {% for href, id, caption in navigation_bar %}
-      <li{% if id == active_page %} class="active"{% endif
-      %}><a href="{{ href|e }}">{{ caption|e }}</a>/li>
-    {% endfor %}
-    </ul>
-    ...
-
-.. _accessing-the-parent-loop:
-
-Accessing the parent Loop
--------------------------
-
-The special `loop` variable always points to the innermost loop.  If it's
-desired to have access to an outer loop it's possible to alias it::
-
-    <table>
-    {% for row in table %}
-      <tr>
-      {% set rowloop = loop %}
-      {% for cell in row %}
-        <td id="cell-{{ rowloop.index }}-{{ loop.index }}>{{ cell }}</td>
-      {% endfor %}
-      </tr>
-    {% endfor %}
-    </table>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py
deleted file mode 100644
index 7ca9683..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from ambari_jinja2 import Environment
-
-
-env = Environment(line_statement_prefix="#", variable_start_string="${", variable_end_string="}")
-
-
-print env.from_string("""\
-<ul>
-# for item in range(10)
-    <li class="${loop.cycle('odd', 'even')}">${item}</li>
-# endfor
-</ul>\
-""").render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py
deleted file mode 100644
index 96b8f36..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from ambari_jinja2 import Environment
-from ambari_jinja2.loaders import FileSystemLoader
-
-env = Environment(loader=FileSystemLoader('templates'))
-
-tmpl = env.get_template('broken.html')
-print tmpl.render(seq=[3, 2, 4, 5, 3, 2, 0, 2, 1])

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py
deleted file mode 100644
index 10ea11c..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from ambari_jinja2 import Environment
-from ambari_jinja2.loaders import DictLoader
-
-
-env = Environment(loader=DictLoader({
-'a': '''[A[{% block body %}{% endblock %}]]''',
-'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''',
-'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}'''
-}))
-
-
-print env.get_template('c').render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html b/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html
deleted file mode 100644
index 294d5c9..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% from 'subbroken.html' import may_break %}
-<ul>
-{% for item in seq %}
-  <li>{{ may_break(item) }}</li>
-{% endfor %}
-</ul>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html b/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html
deleted file mode 100644
index 245eb7e..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{% macro may_break(item) -%}
-  [{{ item / 0 }}]
-{%- endmacro %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py
deleted file mode 100644
index 721c960..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from ambari_jinja2 import Environment
-from ambari_jinja2.loaders import DictLoader
-
-env = Environment(loader=DictLoader({
-'child.html': u'''\
-{% extends master_layout or 'master.html' %}
-{% include helpers = 'helpers.html' %}
-{% macro get_the_answer() %}42{% endmacro %}
-{% title = 'Hello World' %}
-{% block body %}
-    {{ get_the_answer() }}
-    {{ helpers.conspirate() }}
-{% endblock %}
-''',
-'master.html': u'''\
-<!doctype html>
-<title>{{ title }}</title>
-{% block body %}{% endblock %}
-''',
-'helpers.html': u'''\
-{% macro conspirate() %}23{% endmacro %}
-'''
-}))
-
-
-tmpl = env.get_template("child.html")
-print tmpl.render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py
deleted file mode 100644
index 975f74c..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from ambari_jinja2 import Environment
-
-
-env = Environment(line_statement_prefix='%', variable_start_string="${", variable_end_string="}")
-tmpl = env.from_string("""\
-% macro foo()
-    ${caller(42)}
-% endmacro
-<ul>
-% for item in seq
-    <li>${item}</li>
-% endfor
-</ul>
-% call(var) foo()
-    [${var}]
-% endcall
-% filter escape
-    <hello world>
-    % for item in [1, 2, 3]
-      -  ${item}
-    % endfor
-% endfilter
-""")
-
-print tmpl.render(seq=range(10))

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py
deleted file mode 100644
index 051ca42..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from ambari_jinja2 import Environment
-
-tmpl = Environment().from_string("""\
-<ul>
-{%- for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if item % 2 == 0 %}
-    <li>{{ loop.index }} / {{ loop.length }}: {{ item }}</li>
-{%- endfor %}
-</ul>
-if condition: {{ 1 if foo else 0 }}
-""")
-
-print tmpl.render(foo=True)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py
deleted file mode 100644
index 7bada71..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from ambari_jinja2 import Environment
-
-print Environment(extensions=['ambari_jinja2.i18n.TransExtension']).from_string("""\
-{% trans %}Hello {{ user }}!{% endtrans %}
-{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
-""").render(user="someone")


[35/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/bccache.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/bccache.py b/ambari-common/src/main/python/jinja2/jinja2/bccache.py
deleted file mode 100644
index 1e2236c..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/bccache.py
+++ /dev/null
@@ -1,280 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.bccache
-    ~~~~~~~~~~~~~~
-
-    This module implements the bytecode cache system Jinja is optionally
-    using.  This is useful if you have very complex template situations and
-    the compiliation of all those templates slow down your application too
-    much.
-
-    Situations where this is useful are often forking web applications that
-    are initialized on the first request.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from os import path, listdir
-import marshal
-import tempfile
-import cPickle as pickle
-import fnmatch
-from cStringIO import StringIO
-try:
-    from hashlib import sha1
-except ImportError:
-    from sha import new as sha1
-from jinja2.utils import open_if_exists
-
-
-bc_version = 1
-bc_magic = 'j2'.encode('ascii') + pickle.dumps(bc_version, 2)
-
-
-class Bucket(object):
-    """Buckets are used to store the bytecode for one template.  It's created
-    and initialized by the bytecode cache and passed to the loading functions.
-
-    The buckets get an internal checksum from the cache assigned and use this
-    to automatically reject outdated cache material.  Individual bytecode
-    cache subclasses don't have to care about cache invalidation.
-    """
-
-    def __init__(self, environment, key, checksum):
-        self.environment = environment
-        self.key = key
-        self.checksum = checksum
-        self.reset()
-
-    def reset(self):
-        """Resets the bucket (unloads the bytecode)."""
-        self.code = None
-
-    def load_bytecode(self, f):
-        """Loads bytecode from a file or file like object."""
-        # make sure the magic header is correct
-        magic = f.read(len(bc_magic))
-        if magic != bc_magic:
-            self.reset()
-            return
-        # the source code of the file changed, we need to reload
-        checksum = pickle.load(f)
-        if self.checksum != checksum:
-            self.reset()
-            return
-        # now load the code.  Because marshal is not able to load
-        # from arbitrary streams we have to work around that
-        if isinstance(f, file):
-            self.code = marshal.load(f)
-        else:
-            self.code = marshal.loads(f.read())
-
-    def write_bytecode(self, f):
-        """Dump the bytecode into the file or file like object passed."""
-        if self.code is None:
-            raise TypeError('can\'t write empty bucket')
-        f.write(bc_magic)
-        pickle.dump(self.checksum, f, 2)
-        if isinstance(f, file):
-            marshal.dump(self.code, f)
-        else:
-            f.write(marshal.dumps(self.code))
-
-    def bytecode_from_string(self, string):
-        """Load bytecode from a string."""
-        self.load_bytecode(StringIO(string))
-
-    def bytecode_to_string(self):
-        """Return the bytecode as string."""
-        out = StringIO()
-        self.write_bytecode(out)
-        return out.getvalue()
-
-
-class BytecodeCache(object):
-    """To implement your own bytecode cache you have to subclass this class
-    and override :meth:`load_bytecode` and :meth:`dump_bytecode`.  Both of
-    these methods are passed a :class:`~jinja2.bccache.Bucket`.
-
-    A very basic bytecode cache that saves the bytecode on the file system::
-
-        from os import path
-
-        class MyCache(BytecodeCache):
-
-            def __init__(self, directory):
-                self.directory = directory
-
-            def load_bytecode(self, bucket):
-                filename = path.join(self.directory, bucket.key)
-                if path.exists(filename):
-                    with open(filename, 'rb') as f:
-                        bucket.load_bytecode(f)
-
-            def dump_bytecode(self, bucket):
-                filename = path.join(self.directory, bucket.key)
-                with open(filename, 'wb') as f:
-                    bucket.write_bytecode(f)
-
-    A more advanced version of a filesystem based bytecode cache is part of
-    Jinja2.
-    """
-
-    def load_bytecode(self, bucket):
-        """Subclasses have to override this method to load bytecode into a
-        bucket.  If they are not able to find code in the cache for the
-        bucket, it must not do anything.
-        """
-        raise NotImplementedError()
-
-    def dump_bytecode(self, bucket):
-        """Subclasses have to override this method to write the bytecode
-        from a bucket back to the cache.  If it unable to do so it must not
-        fail silently but raise an exception.
-        """
-        raise NotImplementedError()
-
-    def clear(self):
-        """Clears the cache.  This method is not used by Jinja2 but should be
-        implemented to allow applications to clear the bytecode cache used
-        by a particular environment.
-        """
-
-    def get_cache_key(self, name, filename=None):
-        """Returns the unique hash key for this template name."""
-        hash = sha1(name.encode('utf-8'))
-        if filename is not None:
-            if isinstance(filename, unicode):
-                filename = filename.encode('utf-8')
-            hash.update('|' + filename)
-        return hash.hexdigest()
-
-    def get_source_checksum(self, source):
-        """Returns a checksum for the source."""
-        return sha1(source.encode('utf-8')).hexdigest()
-
-    def get_bucket(self, environment, name, filename, source):
-        """Return a cache bucket for the given template.  All arguments are
-        mandatory but filename may be `None`.
-        """
-        key = self.get_cache_key(name, filename)
-        checksum = self.get_source_checksum(source)
-        bucket = Bucket(environment, key, checksum)
-        self.load_bytecode(bucket)
-        return bucket
-
-    def set_bucket(self, bucket):
-        """Put the bucket into the cache."""
-        self.dump_bytecode(bucket)
-
-
-class FileSystemBytecodeCache(BytecodeCache):
-    """A bytecode cache that stores bytecode on the filesystem.  It accepts
-    two arguments: The directory where the cache items are stored and a
-    pattern string that is used to build the filename.
-
-    If no directory is specified the system temporary items folder is used.
-
-    The pattern can be used to have multiple separate caches operate on the
-    same directory.  The default pattern is ``'__jinja2_%s.cache'``.  ``%s``
-    is replaced with the cache key.
-
-    >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
-
-    This bytecode cache supports clearing of the cache using the clear method.
-    """
-
-    def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
-        if directory is None:
-            directory = tempfile.gettempdir()
-        self.directory = directory
-        self.pattern = pattern
-
-    def _get_cache_filename(self, bucket):
-        return path.join(self.directory, self.pattern % bucket.key)
-
-    def load_bytecode(self, bucket):
-        f = open_if_exists(self._get_cache_filename(bucket), 'rb')
-        if f is not None:
-            try:
-                bucket.load_bytecode(f)
-            finally:
-                f.close()
-
-    def dump_bytecode(self, bucket):
-        f = open(self._get_cache_filename(bucket), 'wb')
-        try:
-            bucket.write_bytecode(f)
-        finally:
-            f.close()
-
-    def clear(self):
-        # imported lazily here because google app-engine doesn't support
-        # write access on the file system and the function does not exist
-        # normally.
-        from os import remove
-        files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
-        for filename in files:
-            try:
-                remove(path.join(self.directory, filename))
-            except OSError:
-                pass
-
-
-class MemcachedBytecodeCache(BytecodeCache):
-    """This class implements a bytecode cache that uses a memcache cache for
-    storing the information.  It does not enforce a specific memcache library
-    (tummy's memcache or cmemcache) but will accept any class that provides
-    the minimal interface required.
-
-    Libraries compatible with this class:
-
-    -   `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
-    -   `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
-    -   `cmemcache <http://gijsbert.org/cmemcache/>`_
-
-    (Unfortunately the django cache interface is not compatible because it
-    does not support storing binary data, only unicode.  You can however pass
-    the underlying cache client to the bytecode cache which is available
-    as `django.core.cache.cache._client`.)
-
-    The minimal interface for the client passed to the constructor is this:
-
-    .. class:: MinimalClientInterface
-
-        .. method:: set(key, value[, timeout])
-
-            Stores the bytecode in the cache.  `value` is a string and
-            `timeout` the timeout of the key.  If timeout is not provided
-            a default timeout or no timeout should be assumed, if it's
-            provided it's an integer with the number of seconds the cache
-            item should exist.
-
-        .. method:: get(key)
-
-            Returns the value for the cache key.  If the item does not
-            exist in the cache the return value must be `None`.
-
-    The other arguments to the constructor are the prefix for all keys that
-    is added before the actual cache key and the timeout for the bytecode in
-    the cache system.  We recommend a high (or no) timeout.
-
-    This bytecode cache does not support clearing of used items in the cache.
-    The clear method is a no-operation function.
-    """
-
-    def __init__(self, client, prefix='jinja2/bytecode/', timeout=None):
-        self.client = client
-        self.prefix = prefix
-        self.timeout = timeout
-
-    def load_bytecode(self, bucket):
-        code = self.client.get(self.prefix + bucket.key)
-        if code is not None:
-            bucket.bytecode_from_string(code)
-
-    def dump_bytecode(self, bucket):
-        args = (self.prefix + bucket.key, bucket.bytecode_to_string())
-        if self.timeout is not None:
-            args += (self.timeout,)
-        self.client.set(*args)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/compiler.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/compiler.py b/ambari-common/src/main/python/jinja2/jinja2/compiler.py
deleted file mode 100644
index 5764159..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/compiler.py
+++ /dev/null
@@ -1,1640 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.compiler
-    ~~~~~~~~~~~~~~~
-
-    Compiles nodes into python code.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from cStringIO import StringIO
-from itertools import chain
-from copy import deepcopy
-from jinja2 import nodes
-from jinja2.nodes import EvalContext
-from jinja2.visitor import NodeVisitor, NodeTransformer
-from jinja2.exceptions import TemplateAssertionError
-from jinja2.utils import Markup, concat, escape, is_python_keyword, next
-
-
-operators = {
-    'eq':       '==',
-    'ne':       '!=',
-    'gt':       '>',
-    'gteq':     '>=',
-    'lt':       '<',
-    'lteq':     '<=',
-    'in':       'in',
-    'notin':    'not in'
-}
-
-try:
-    exec '(0 if 0 else 0)'
-except SyntaxError:
-    have_condexpr = False
-else:
-    have_condexpr = True
-
-
-# what method to iterate over items do we want to use for dict iteration
-# in generated code?  on 2.x let's go with iteritems, on 3.x with items
-if hasattr(dict, 'iteritems'):
-    dict_item_iter = 'iteritems'
-else:
-    dict_item_iter = 'items'
-
-
-# does if 0: dummy(x) get us x into the scope?
-def unoptimize_before_dead_code():
-    x = 42
-    def f():
-        if 0: dummy(x)
-    return f
-unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
-
-
-def generate(node, environment, name, filename, stream=None,
-             defer_init=False):
-    """Generate the python source for a node tree."""
-    if not isinstance(node, nodes.Template):
-        raise TypeError('Can\'t compile non template nodes')
-    generator = CodeGenerator(environment, name, filename, stream, defer_init)
-    generator.visit(node)
-    if stream is None:
-        return generator.stream.getvalue()
-
-
-def has_safe_repr(value):
-    """Does the node have a safe representation?"""
-    if value is None or value is NotImplemented or value is Ellipsis:
-        return True
-    if isinstance(value, (bool, int, long, float, complex, basestring,
-                          xrange, Markup)):
-        return True
-    if isinstance(value, (tuple, list, set, frozenset)):
-        for item in value:
-            if not has_safe_repr(item):
-                return False
-        return True
-    elif isinstance(value, dict):
-        for key, value in value.iteritems():
-            if not has_safe_repr(key):
-                return False
-            if not has_safe_repr(value):
-                return False
-        return True
-    return False
-
-
-def find_undeclared(nodes, names):
-    """Check if the names passed are accessed undeclared.  The return value
-    is a set of all the undeclared names from the sequence of names found.
-    """
-    visitor = UndeclaredNameVisitor(names)
-    try:
-        for node in nodes:
-            visitor.visit(node)
-    except VisitorExit:
-        pass
-    return visitor.undeclared
-
-
-class Identifiers(object):
-    """Tracks the status of identifiers in frames."""
-
-    def __init__(self):
-        # variables that are known to be declared (probably from outer
-        # frames or because they are special for the frame)
-        self.declared = set()
-
-        # undeclared variables from outer scopes
-        self.outer_undeclared = set()
-
-        # names that are accessed without being explicitly declared by
-        # this one or any of the outer scopes.  Names can appear both in
-        # declared and undeclared.
-        self.undeclared = set()
-
-        # names that are declared locally
-        self.declared_locally = set()
-
-        # names that are declared by parameters
-        self.declared_parameter = set()
-
-    def add_special(self, name):
-        """Register a special name like `loop`."""
-        self.undeclared.discard(name)
-        self.declared.add(name)
-
-    def is_declared(self, name, local_only=False):
-        """Check if a name is declared in this or an outer scope."""
-        if name in self.declared_locally or name in self.declared_parameter:
-            return True
-        if local_only:
-            return False
-        return name in self.declared
-
-    def copy(self):
-        return deepcopy(self)
-
-
-class Frame(object):
-    """Holds compile time information for us."""
-
-    def __init__(self, eval_ctx, parent=None):
-        self.eval_ctx = eval_ctx
-        self.identifiers = Identifiers()
-
-        # a toplevel frame is the root + soft frames such as if conditions.
-        self.toplevel = False
-
-        # the root frame is basically just the outermost frame, so no if
-        # conditions.  This information is used to optimize inheritance
-        # situations.
-        self.rootlevel = False
-
-        # in some dynamic inheritance situations the compiler needs to add
-        # write tests around output statements.
-        self.require_output_check = parent and parent.require_output_check
-
-        # inside some tags we are using a buffer rather than yield statements.
-        # this for example affects {% filter %} or {% macro %}.  If a frame
-        # is buffered this variable points to the name of the list used as
-        # buffer.
-        self.buffer = None
-
-        # the name of the block we're in, otherwise None.
-        self.block = parent and parent.block or None
-
-        # a set of actually assigned names
-        self.assigned_names = set()
-
-        # the parent of this frame
-        self.parent = parent
-
-        if parent is not None:
-            self.identifiers.declared.update(
-                parent.identifiers.declared |
-                parent.identifiers.declared_parameter |
-                parent.assigned_names
-            )
-            self.identifiers.outer_undeclared.update(
-                parent.identifiers.undeclared -
-                self.identifiers.declared
-            )
-            self.buffer = parent.buffer
-
-    def copy(self):
-        """Create a copy of the current one."""
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.identifiers = object.__new__(self.identifiers.__class__)
-        rv.identifiers.__dict__.update(self.identifiers.__dict__)
-        return rv
-
-    def inspect(self, nodes, hard_scope=False):
-        """Walk the node and check for identifiers.  If the scope is hard (eg:
-        enforce on a python level) overrides from outer scopes are tracked
-        differently.
-        """
-        visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
-        for node in nodes:
-            visitor.visit(node)
-
-    def find_shadowed(self, extra=()):
-        """Find all the shadowed names.  extra is an iterable of variables
-        that may be defined with `add_special` which may occour scoped.
-        """
-        i = self.identifiers
-        return (i.declared | i.outer_undeclared) & \
-               (i.declared_locally | i.declared_parameter) | \
-               set(x for x in extra if i.is_declared(x))
-
-    def inner(self):
-        """Return an inner frame."""
-        return Frame(self.eval_ctx, self)
-
-    def soft(self):
-        """Return a soft frame.  A soft frame may not be modified as
-        standalone thing as it shares the resources with the frame it
-        was created of, but it's not a rootlevel frame any longer.
-        """
-        rv = self.copy()
-        rv.rootlevel = False
-        return rv
-
-    __copy__ = copy
-
-
-class VisitorExit(RuntimeError):
-    """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
-
-
-class DependencyFinderVisitor(NodeVisitor):
-    """A visitor that collects filter and test calls."""
-
-    def __init__(self):
-        self.filters = set()
-        self.tests = set()
-
-    def visit_Filter(self, node):
-        self.generic_visit(node)
-        self.filters.add(node.name)
-
-    def visit_Test(self, node):
-        self.generic_visit(node)
-        self.tests.add(node.name)
-
-    def visit_Block(self, node):
-        """Stop visiting at blocks."""
-
-
-class UndeclaredNameVisitor(NodeVisitor):
-    """A visitor that checks if a name is accessed without being
-    declared.  This is different from the frame visitor as it will
-    not stop at closure frames.
-    """
-
-    def __init__(self, names):
-        self.names = set(names)
-        self.undeclared = set()
-
-    def visit_Name(self, node):
-        if node.ctx == 'load' and node.name in self.names:
-            self.undeclared.add(node.name)
-            if self.undeclared == self.names:
-                raise VisitorExit()
-        else:
-            self.names.discard(node.name)
-
-    def visit_Block(self, node):
-        """Stop visiting a blocks."""
-
-
-class FrameIdentifierVisitor(NodeVisitor):
-    """A visitor for `Frame.inspect`."""
-
-    def __init__(self, identifiers, hard_scope):
-        self.identifiers = identifiers
-        self.hard_scope = hard_scope
-
-    def visit_Name(self, node):
-        """All assignments to names go through this function."""
-        if node.ctx == 'store':
-            self.identifiers.declared_locally.add(node.name)
-        elif node.ctx == 'param':
-            self.identifiers.declared_parameter.add(node.name)
-        elif node.ctx == 'load' and not \
-             self.identifiers.is_declared(node.name, self.hard_scope):
-            self.identifiers.undeclared.add(node.name)
-
-    def visit_If(self, node):
-        self.visit(node.test)
-        real_identifiers = self.identifiers
-
-        old_names = real_identifiers.declared_locally | \
-                    real_identifiers.declared_parameter
-
-        def inner_visit(nodes):
-            if not nodes:
-                return set()
-            self.identifiers = real_identifiers.copy()
-            for subnode in nodes:
-                self.visit(subnode)
-            rv = self.identifiers.declared_locally - old_names
-            # we have to remember the undeclared variables of this branch
-            # because we will have to pull them.
-            real_identifiers.undeclared.update(self.identifiers.undeclared)
-            self.identifiers = real_identifiers
-            return rv
-
-        body = inner_visit(node.body)
-        else_ = inner_visit(node.else_ or ())
-
-        # the differences between the two branches are also pulled as
-        # undeclared variables
-        real_identifiers.undeclared.update(body.symmetric_difference(else_) -
-                                           real_identifiers.declared)
-
-        # remember those that are declared.
-        real_identifiers.declared_locally.update(body | else_)
-
-    def visit_Macro(self, node):
-        self.identifiers.declared_locally.add(node.name)
-
-    def visit_Import(self, node):
-        self.generic_visit(node)
-        self.identifiers.declared_locally.add(node.target)
-
-    def visit_FromImport(self, node):
-        self.generic_visit(node)
-        for name in node.names:
-            if isinstance(name, tuple):
-                self.identifiers.declared_locally.add(name[1])
-            else:
-                self.identifiers.declared_locally.add(name)
-
-    def visit_Assign(self, node):
-        """Visit assignments in the correct order."""
-        self.visit(node.node)
-        self.visit(node.target)
-
-    def visit_For(self, node):
-        """Visiting stops at for blocks.  However the block sequence
-        is visited as part of the outer scope.
-        """
-        self.visit(node.iter)
-
-    def visit_CallBlock(self, node):
-        self.visit(node.call)
-
-    def visit_FilterBlock(self, node):
-        self.visit(node.filter)
-
-    def visit_Scope(self, node):
-        """Stop visiting at scopes."""
-
-    def visit_Block(self, node):
-        """Stop visiting at blocks."""
-
-
-class CompilerExit(Exception):
-    """Raised if the compiler encountered a situation where it just
-    doesn't make sense to further process the code.  Any block that
-    raises such an exception is not further processed.
-    """
-
-
-class CodeGenerator(NodeVisitor):
-
-    def __init__(self, environment, name, filename, stream=None,
-                 defer_init=False):
-        if stream is None:
-            stream = StringIO()
-        self.environment = environment
-        self.name = name
-        self.filename = filename
-        self.stream = stream
-        self.created_block_context = False
-        self.defer_init = defer_init
-
-        # aliases for imports
-        self.import_aliases = {}
-
-        # a registry for all blocks.  Because blocks are moved out
-        # into the global python scope they are registered here
-        self.blocks = {}
-
-        # the number of extends statements so far
-        self.extends_so_far = 0
-
-        # some templates have a rootlevel extends.  In this case we
-        # can safely assume that we're a child template and do some
-        # more optimizations.
-        self.has_known_extends = False
-
-        # the current line number
-        self.code_lineno = 1
-
-        # registry of all filters and tests (global, not block local)
-        self.tests = {}
-        self.filters = {}
-
-        # the debug information
-        self.debug_info = []
-        self._write_debug_info = None
-
-        # the number of new lines before the next write()
-        self._new_lines = 0
-
-        # the line number of the last written statement
-        self._last_line = 0
-
-        # true if nothing was written so far.
-        self._first_write = True
-
-        # used by the `temporary_identifier` method to get new
-        # unique, temporary identifier
-        self._last_identifier = 0
-
-        # the current indentation
-        self._indentation = 0
-
-    # -- Various compilation helpers
-
-    def fail(self, msg, lineno):
-        """Fail with a :exc:`TemplateAssertionError`."""
-        raise TemplateAssertionError(msg, lineno, self.name, self.filename)
-
-    def temporary_identifier(self):
-        """Get a new unique identifier."""
-        self._last_identifier += 1
-        return 't_%d' % self._last_identifier
-
-    def buffer(self, frame):
-        """Enable buffering for the frame from that point onwards."""
-        frame.buffer = self.temporary_identifier()
-        self.writeline('%s = []' % frame.buffer)
-
-    def return_buffer_contents(self, frame):
-        """Return the buffer contents of the frame."""
-        if frame.eval_ctx.volatile:
-            self.writeline('if context.eval_ctx.autoescape:')
-            self.indent()
-            self.writeline('return Markup(concat(%s))' % frame.buffer)
-            self.outdent()
-            self.writeline('else:')
-            self.indent()
-            self.writeline('return concat(%s)' % frame.buffer)
-            self.outdent()
-        elif frame.eval_ctx.autoescape:
-            self.writeline('return Markup(concat(%s))' % frame.buffer)
-        else:
-            self.writeline('return concat(%s)' % frame.buffer)
-
-    def indent(self):
-        """Indent by one."""
-        self._indentation += 1
-
-    def outdent(self, step=1):
-        """Outdent by step."""
-        self._indentation -= step
-
-    def start_write(self, frame, node=None):
-        """Yield or write into the frame buffer."""
-        if frame.buffer is None:
-            self.writeline('yield ', node)
-        else:
-            self.writeline('%s.append(' % frame.buffer, node)
-
-    def end_write(self, frame):
-        """End the writing process started by `start_write`."""
-        if frame.buffer is not None:
-            self.write(')')
-
-    def simple_write(self, s, frame, node=None):
-        """Simple shortcut for start_write + write + end_write."""
-        self.start_write(frame, node)
-        self.write(s)
-        self.end_write(frame)
-
-    def blockvisit(self, nodes, frame):
-        """Visit a list of nodes as block in a frame.  If the current frame
-        is no buffer a dummy ``if 0: yield None`` is written automatically
-        unless the force_generator parameter is set to False.
-        """
-        if frame.buffer is None:
-            self.writeline('if 0: yield None')
-        else:
-            self.writeline('pass')
-        try:
-            for node in nodes:
-                self.visit(node, frame)
-        except CompilerExit:
-            pass
-
-    def write(self, x):
-        """Write a string into the output stream."""
-        if self._new_lines:
-            if not self._first_write:
-                self.stream.write('\n' * self._new_lines)
-                self.code_lineno += self._new_lines
-                if self._write_debug_info is not None:
-                    self.debug_info.append((self._write_debug_info,
-                                            self.code_lineno))
-                    self._write_debug_info = None
-            self._first_write = False
-            self.stream.write('    ' * self._indentation)
-            self._new_lines = 0
-        self.stream.write(x)
-
-    def writeline(self, x, node=None, extra=0):
-        """Combination of newline and write."""
-        self.newline(node, extra)
-        self.write(x)
-
-    def newline(self, node=None, extra=0):
-        """Add one or more newlines before the next write."""
-        self._new_lines = max(self._new_lines, 1 + extra)
-        if node is not None and node.lineno != self._last_line:
-            self._write_debug_info = node.lineno
-            self._last_line = node.lineno
-
-    def signature(self, node, frame, extra_kwargs=None):
-        """Writes a function call to the stream for the current node.
-        A leading comma is added automatically.  The extra keyword
-        arguments may not include python keywords otherwise a syntax
-        error could occour.  The extra keyword arguments should be given
-        as python dict.
-        """
-        # if any of the given keyword arguments is a python keyword
-        # we have to make sure that no invalid call is created.
-        kwarg_workaround = False
-        for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
-            if is_python_keyword(kwarg):
-                kwarg_workaround = True
-                break
-
-        for arg in node.args:
-            self.write(', ')
-            self.visit(arg, frame)
-
-        if not kwarg_workaround:
-            for kwarg in node.kwargs:
-                self.write(', ')
-                self.visit(kwarg, frame)
-            if extra_kwargs is not None:
-                for key, value in extra_kwargs.iteritems():
-                    self.write(', %s=%s' % (key, value))
-        if node.dyn_args:
-            self.write(', *')
-            self.visit(node.dyn_args, frame)
-
-        if kwarg_workaround:
-            if node.dyn_kwargs is not None:
-                self.write(', **dict({')
-            else:
-                self.write(', **{')
-            for kwarg in node.kwargs:
-                self.write('%r: ' % kwarg.key)
-                self.visit(kwarg.value, frame)
-                self.write(', ')
-            if extra_kwargs is not None:
-                for key, value in extra_kwargs.iteritems():
-                    self.write('%r: %s, ' % (key, value))
-            if node.dyn_kwargs is not None:
-                self.write('}, **')
-                self.visit(node.dyn_kwargs, frame)
-                self.write(')')
-            else:
-                self.write('}')
-
-        elif node.dyn_kwargs is not None:
-            self.write(', **')
-            self.visit(node.dyn_kwargs, frame)
-
-    def pull_locals(self, frame):
-        """Pull all the references identifiers into the local scope."""
-        for name in frame.identifiers.undeclared:
-            self.writeline('l_%s = context.resolve(%r)' % (name, name))
-
-    def pull_dependencies(self, nodes):
-        """Pull all the dependencies."""
-        visitor = DependencyFinderVisitor()
-        for node in nodes:
-            visitor.visit(node)
-        for dependency in 'filters', 'tests':
-            mapping = getattr(self, dependency)
-            for name in getattr(visitor, dependency):
-                if name not in mapping:
-                    mapping[name] = self.temporary_identifier()
-                self.writeline('%s = environment.%s[%r]' %
-                               (mapping[name], dependency, name))
-
-    def unoptimize_scope(self, frame):
-        """Disable Python optimizations for the frame."""
-        # XXX: this is not that nice but it has no real overhead.  It
-        # mainly works because python finds the locals before dead code
-        # is removed.  If that breaks we have to add a dummy function
-        # that just accepts the arguments and does nothing.
-        if frame.identifiers.declared:
-            self.writeline('%sdummy(%s)' % (
-                unoptimize_before_dead_code and 'if 0: ' or '',
-                ', '.join('l_' + name for name in frame.identifiers.declared)
-            ))
-
-    def push_scope(self, frame, extra_vars=()):
-        """This function returns all the shadowed variables in a dict
-        in the form name: alias and will write the required assignments
-        into the current scope.  No indentation takes place.
-
-        This also predefines locally declared variables from the loop
-        body because under some circumstances it may be the case that
-
-        `extra_vars` is passed to `Frame.find_shadowed`.
-        """
-        aliases = {}
-        for name in frame.find_shadowed(extra_vars):
-            aliases[name] = ident = self.temporary_identifier()
-            self.writeline('%s = l_%s' % (ident, name))
-        to_declare = set()
-        for name in frame.identifiers.declared_locally:
-            if name not in aliases:
-                to_declare.add('l_' + name)
-        if to_declare:
-            self.writeline(' = '.join(to_declare) + ' = missing')
-        return aliases
-
-    def pop_scope(self, aliases, frame):
-        """Restore all aliases and delete unused variables."""
-        for name, alias in aliases.iteritems():
-            self.writeline('l_%s = %s' % (name, alias))
-        to_delete = set()
-        for name in frame.identifiers.declared_locally:
-            if name not in aliases:
-                to_delete.add('l_' + name)
-        if to_delete:
-            # we cannot use the del statement here because enclosed
-            # scopes can trigger a SyntaxError:
-            #   a = 42; b = lambda: a; del a
-            self.writeline(' = '.join(to_delete) + ' = missing')
-
-    def function_scoping(self, node, frame, children=None,
-                         find_special=True):
-        """In Jinja a few statements require the help of anonymous
-        functions.  Those are currently macros and call blocks and in
-        the future also recursive loops.  As there is currently
-        technical limitation that doesn't allow reading and writing a
-        variable in a scope where the initial value is coming from an
-        outer scope, this function tries to fall back with a common
-        error message.  Additionally the frame passed is modified so
-        that the argumetns are collected and callers are looked up.
-
-        This will return the modified frame.
-        """
-        # we have to iterate twice over it, make sure that works
-        if children is None:
-            children = node.iter_child_nodes()
-        children = list(children)
-        func_frame = frame.inner()
-        func_frame.inspect(children, hard_scope=True)
-
-        # variables that are undeclared (accessed before declaration) and
-        # declared locally *and* part of an outside scope raise a template
-        # assertion error. Reason: we can't generate reasonable code from
-        # it without aliasing all the variables.
-        # this could be fixed in Python 3 where we have the nonlocal
-        # keyword or if we switch to bytecode generation
-        overriden_closure_vars = (
-            func_frame.identifiers.undeclared &
-            func_frame.identifiers.declared &
-            (func_frame.identifiers.declared_locally |
-             func_frame.identifiers.declared_parameter)
-        )
-        if overriden_closure_vars:
-            self.fail('It\'s not possible to set and access variables '
-                      'derived from an outer scope! (affects: %s)' %
-                      ', '.join(sorted(overriden_closure_vars)), node.lineno)
-
-        # remove variables from a closure from the frame's undeclared
-        # identifiers.
-        func_frame.identifiers.undeclared -= (
-            func_frame.identifiers.undeclared &
-            func_frame.identifiers.declared
-        )
-
-        # no special variables for this scope, abort early
-        if not find_special:
-            return func_frame
-
-        func_frame.accesses_kwargs = False
-        func_frame.accesses_varargs = False
-        func_frame.accesses_caller = False
-        func_frame.arguments = args = ['l_' + x.name for x in node.args]
-
-        undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
-
-        if 'caller' in undeclared:
-            func_frame.accesses_caller = True
-            func_frame.identifiers.add_special('caller')
-            args.append('l_caller')
-        if 'kwargs' in undeclared:
-            func_frame.accesses_kwargs = True
-            func_frame.identifiers.add_special('kwargs')
-            args.append('l_kwargs')
-        if 'varargs' in undeclared:
-            func_frame.accesses_varargs = True
-            func_frame.identifiers.add_special('varargs')
-            args.append('l_varargs')
-        return func_frame
-
-    def macro_body(self, node, frame, children=None):
-        """Dump the function def of a macro or call block."""
-        frame = self.function_scoping(node, frame, children)
-        # macros are delayed, they never require output checks
-        frame.require_output_check = False
-        args = frame.arguments
-        # XXX: this is an ugly fix for the loop nesting bug
-        # (tests.test_old_bugs.test_loop_call_bug).  This works around
-        # a identifier nesting problem we have in general.  It's just more
-        # likely to happen in loops which is why we work around it.  The
-        # real solution would be "nonlocal" all the identifiers that are
-        # leaking into a new python frame and might be used both unassigned
-        # and assigned.
-        if 'loop' in frame.identifiers.declared:
-            args = args + ['l_loop=l_loop']
-        self.writeline('def macro(%s):' % ', '.join(args), node)
-        self.indent()
-        self.buffer(frame)
-        self.pull_locals(frame)
-        self.blockvisit(node.body, frame)
-        self.return_buffer_contents(frame)
-        self.outdent()
-        return frame
-
-    def macro_def(self, node, frame):
-        """Dump the macro definition for the def created by macro_body."""
-        arg_tuple = ', '.join(repr(x.name) for x in node.args)
-        name = getattr(node, 'name', None)
-        if len(node.args) == 1:
-            arg_tuple += ','
-        self.write('Macro(environment, macro, %r, (%s), (' %
-                   (name, arg_tuple))
-        for arg in node.defaults:
-            self.visit(arg, frame)
-            self.write(', ')
-        self.write('), %r, %r, %r)' % (
-            bool(frame.accesses_kwargs),
-            bool(frame.accesses_varargs),
-            bool(frame.accesses_caller)
-        ))
-
-    def position(self, node):
-        """Return a human readable position for the node."""
-        rv = 'line %d' % node.lineno
-        if self.name is not None:
-            rv += ' in ' + repr(self.name)
-        return rv
-
-    # -- Statement Visitors
-
-    def visit_Template(self, node, frame=None):
-        assert frame is None, 'no root frame allowed'
-        eval_ctx = EvalContext(self.environment, self.name)
-
-        from jinja2.runtime import __all__ as exported
-        self.writeline('from __future__ import division')
-        self.writeline('from jinja2.runtime import ' + ', '.join(exported))
-        if not unoptimize_before_dead_code:
-            self.writeline('dummy = lambda *x: None')
-
-        # if we want a deferred initialization we cannot move the
-        # environment into a local name
-        envenv = not self.defer_init and ', environment=environment' or ''
-
-        # do we have an extends tag at all?  If not, we can save some
-        # overhead by just not processing any inheritance code.
-        have_extends = node.find(nodes.Extends) is not None
-
-        # find all blocks
-        for block in node.find_all(nodes.Block):
-            if block.name in self.blocks:
-                self.fail('block %r defined twice' % block.name, block.lineno)
-            self.blocks[block.name] = block
-
-        # find all imports and import them
-        for import_ in node.find_all(nodes.ImportedName):
-            if import_.importname not in self.import_aliases:
-                imp = import_.importname
-                self.import_aliases[imp] = alias = self.temporary_identifier()
-                if '.' in imp:
-                    module, obj = imp.rsplit('.', 1)
-                    self.writeline('from %s import %s as %s' %
-                                   (module, obj, alias))
-                else:
-                    self.writeline('import %s as %s' % (imp, alias))
-
-        # add the load name
-        self.writeline('name = %r' % self.name)
-
-        # generate the root render function.
-        self.writeline('def root(context%s):' % envenv, extra=1)
-
-        # process the root
-        frame = Frame(eval_ctx)
-        frame.inspect(node.body)
-        frame.toplevel = frame.rootlevel = True
-        frame.require_output_check = have_extends and not self.has_known_extends
-        self.indent()
-        if have_extends:
-            self.writeline('parent_template = None')
-        if 'self' in find_undeclared(node.body, ('self',)):
-            frame.identifiers.add_special('self')
-            self.writeline('l_self = TemplateReference(context)')
-        self.pull_locals(frame)
-        self.pull_dependencies(node.body)
-        self.blockvisit(node.body, frame)
-        self.outdent()
-
-        # make sure that the parent root is called.
-        if have_extends:
-            if not self.has_known_extends:
-                self.indent()
-                self.writeline('if parent_template is not None:')
-            self.indent()
-            self.writeline('for event in parent_template.'
-                           'root_render_func(context):')
-            self.indent()
-            self.writeline('yield event')
-            self.outdent(2 + (not self.has_known_extends))
-
-        # at this point we now have the blocks collected and can visit them too.
-        for name, block in self.blocks.iteritems():
-            block_frame = Frame(eval_ctx)
-            block_frame.inspect(block.body)
-            block_frame.block = name
-            self.writeline('def block_%s(context%s):' % (name, envenv),
-                           block, 1)
-            self.indent()
-            undeclared = find_undeclared(block.body, ('self', 'super'))
-            if 'self' in undeclared:
-                block_frame.identifiers.add_special('self')
-                self.writeline('l_self = TemplateReference(context)')
-            if 'super' in undeclared:
-                block_frame.identifiers.add_special('super')
-                self.writeline('l_super = context.super(%r, '
-                               'block_%s)' % (name, name))
-            self.pull_locals(block_frame)
-            self.pull_dependencies(block.body)
-            self.blockvisit(block.body, block_frame)
-            self.outdent()
-
-        self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
-                                                   for x in self.blocks),
-                       extra=1)
-
-        # add a function that returns the debug info
-        self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
-                                                    in self.debug_info))
-
-    def visit_Block(self, node, frame):
-        """Call a block and register it for the template."""
-        level = 1
-        if frame.toplevel:
-            # if we know that we are a child template, there is no need to
-            # check if we are one
-            if self.has_known_extends:
-                return
-            if self.extends_so_far > 0:
-                self.writeline('if parent_template is None:')
-                self.indent()
-                level += 1
-        context = node.scoped and 'context.derived(locals())' or 'context'
-        self.writeline('for event in context.blocks[%r][0](%s):' % (
-                       node.name, context), node)
-        self.indent()
-        self.simple_write('event', frame)
-        self.outdent(level)
-
-    def visit_Extends(self, node, frame):
-        """Calls the extender."""
-        if not frame.toplevel:
-            self.fail('cannot use extend from a non top-level scope',
-                      node.lineno)
-
-        # if the number of extends statements in general is zero so
-        # far, we don't have to add a check if something extended
-        # the template before this one.
-        if self.extends_so_far > 0:
-
-            # if we have a known extends we just add a template runtime
-            # error into the generated code.  We could catch that at compile
-            # time too, but i welcome it not to confuse users by throwing the
-            # same error at different times just "because we can".
-            if not self.has_known_extends:
-                self.writeline('if parent_template is not None:')
-                self.indent()
-            self.writeline('raise TemplateRuntimeError(%r)' %
-                           'extended multiple times')
-            self.outdent()
-
-            # if we have a known extends already we don't need that code here
-            # as we know that the template execution will end here.
-            if self.has_known_extends:
-                raise CompilerExit()
-
-        self.writeline('parent_template = environment.get_template(', node)
-        self.visit(node.template, frame)
-        self.write(', %r)' % self.name)
-        self.writeline('for name, parent_block in parent_template.'
-                       'blocks.%s():' % dict_item_iter)
-        self.indent()
-        self.writeline('context.blocks.setdefault(name, []).'
-                       'append(parent_block)')
-        self.outdent()
-
-        # if this extends statement was in the root level we can take
-        # advantage of that information and simplify the generated code
-        # in the top level from this point onwards
-        if frame.rootlevel:
-            self.has_known_extends = True
-
-        # and now we have one more
-        self.extends_so_far += 1
-
-    def visit_Include(self, node, frame):
-        """Handles includes."""
-        if node.with_context:
-            self.unoptimize_scope(frame)
-        if node.ignore_missing:
-            self.writeline('try:')
-            self.indent()
-
-        func_name = 'get_or_select_template'
-        if isinstance(node.template, nodes.Const):
-            if isinstance(node.template.value, basestring):
-                func_name = 'get_template'
-            elif isinstance(node.template.value, (tuple, list)):
-                func_name = 'select_template'
-        elif isinstance(node.template, (nodes.Tuple, nodes.List)):
-            func_name = 'select_template'
-
-        self.writeline('template = environment.%s(' % func_name, node)
-        self.visit(node.template, frame)
-        self.write(', %r)' % self.name)
-        if node.ignore_missing:
-            self.outdent()
-            self.writeline('except TemplateNotFound:')
-            self.indent()
-            self.writeline('pass')
-            self.outdent()
-            self.writeline('else:')
-            self.indent()
-
-        if node.with_context:
-            self.writeline('for event in template.root_render_func('
-                           'template.new_context(context.parent, True, '
-                           'locals())):')
-        else:
-            self.writeline('for event in template.module._body_stream:')
-
-        self.indent()
-        self.simple_write('event', frame)
-        self.outdent()
-
-        if node.ignore_missing:
-            self.outdent()
-
-    def visit_Import(self, node, frame):
-        """Visit regular imports."""
-        if node.with_context:
-            self.unoptimize_scope(frame)
-        self.writeline('l_%s = ' % node.target, node)
-        if frame.toplevel:
-            self.write('context.vars[%r] = ' % node.target)
-        self.write('environment.get_template(')
-        self.visit(node.template, frame)
-        self.write(', %r).' % self.name)
-        if node.with_context:
-            self.write('make_module(context.parent, True, locals())')
-        else:
-            self.write('module')
-        if frame.toplevel and not node.target.startswith('_'):
-            self.writeline('context.exported_vars.discard(%r)' % node.target)
-        frame.assigned_names.add(node.target)
-
-    def visit_FromImport(self, node, frame):
-        """Visit named imports."""
-        self.newline(node)
-        self.write('included_template = environment.get_template(')
-        self.visit(node.template, frame)
-        self.write(', %r).' % self.name)
-        if node.with_context:
-            self.write('make_module(context.parent, True)')
-        else:
-            self.write('module')
-
-        var_names = []
-        discarded_names = []
-        for name in node.names:
-            if isinstance(name, tuple):
-                name, alias = name
-            else:
-                alias = name
-            self.writeline('l_%s = getattr(included_template, '
-                           '%r, missing)' % (alias, name))
-            self.writeline('if l_%s is missing:' % alias)
-            self.indent()
-            self.writeline('l_%s = environment.undefined(%r %% '
-                           'included_template.__name__, '
-                           'name=%r)' %
-                           (alias, 'the template %%r (imported on %s) does '
-                           'not export the requested name %s' % (
-                                self.position(node),
-                                repr(name)
-                           ), name))
-            self.outdent()
-            if frame.toplevel:
-                var_names.append(alias)
-                if not alias.startswith('_'):
-                    discarded_names.append(alias)
-            frame.assigned_names.add(alias)
-
-        if var_names:
-            if len(var_names) == 1:
-                name = var_names[0]
-                self.writeline('context.vars[%r] = l_%s' % (name, name))
-            else:
-                self.writeline('context.vars.update({%s})' % ', '.join(
-                    '%r: l_%s' % (name, name) for name in var_names
-                ))
-        if discarded_names:
-            if len(discarded_names) == 1:
-                self.writeline('context.exported_vars.discard(%r)' %
-                               discarded_names[0])
-            else:
-                self.writeline('context.exported_vars.difference_'
-                               'update((%s))' % ', '.join(map(repr, discarded_names)))
-
-    def visit_For(self, node, frame):
-        # when calculating the nodes for the inner frame we have to exclude
-        # the iterator contents from it
-        children = node.iter_child_nodes(exclude=('iter',))
-        if node.recursive:
-            loop_frame = self.function_scoping(node, frame, children,
-                                               find_special=False)
-        else:
-            loop_frame = frame.inner()
-            loop_frame.inspect(children)
-
-        # try to figure out if we have an extended loop.  An extended loop
-        # is necessary if the loop is in recursive mode if the special loop
-        # variable is accessed in the body.
-        extended_loop = node.recursive or 'loop' in \
-                        find_undeclared(node.iter_child_nodes(
-                            only=('body',)), ('loop',))
-
-        # if we don't have an recursive loop we have to find the shadowed
-        # variables at that point.  Because loops can be nested but the loop
-        # variable is a special one we have to enforce aliasing for it.
-        if not node.recursive:
-            aliases = self.push_scope(loop_frame, ('loop',))
-
-        # otherwise we set up a buffer and add a function def
-        else:
-            self.writeline('def loop(reciter, loop_render_func):', node)
-            self.indent()
-            self.buffer(loop_frame)
-            aliases = {}
-
-        # make sure the loop variable is a special one and raise a template
-        # assertion error if a loop tries to write to loop
-        if extended_loop:
-            loop_frame.identifiers.add_special('loop')
-        for name in node.find_all(nodes.Name):
-            if name.ctx == 'store' and name.name == 'loop':
-                self.fail('Can\'t assign to special loop variable '
-                          'in for-loop target', name.lineno)
-
-        self.pull_locals(loop_frame)
-        if node.else_:
-            iteration_indicator = self.temporary_identifier()
-            self.writeline('%s = 1' % iteration_indicator)
-
-        # Create a fake parent loop if the else or test section of a
-        # loop is accessing the special loop variable and no parent loop
-        # exists.
-        if 'loop' not in aliases and 'loop' in find_undeclared(
-           node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
-            self.writeline("l_loop = environment.undefined(%r, name='loop')" %
-                ("'loop' is undefined. the filter section of a loop as well "
-                 "as the else block doesn't have access to the special 'loop'"
-                 " variable of the current loop.  Because there is no parent "
-                 "loop it's undefined.  Happened in loop on %s" %
-                 self.position(node)))
-
-        self.writeline('for ', node)
-        self.visit(node.target, loop_frame)
-        self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
-
-        # if we have an extened loop and a node test, we filter in the
-        # "outer frame".
-        if extended_loop and node.test is not None:
-            self.write('(')
-            self.visit(node.target, loop_frame)
-            self.write(' for ')
-            self.visit(node.target, loop_frame)
-            self.write(' in ')
-            if node.recursive:
-                self.write('reciter')
-            else:
-                self.visit(node.iter, loop_frame)
-            self.write(' if (')
-            test_frame = loop_frame.copy()
-            self.visit(node.test, test_frame)
-            self.write('))')
-
-        elif node.recursive:
-            self.write('reciter')
-        else:
-            self.visit(node.iter, loop_frame)
-
-        if node.recursive:
-            self.write(', recurse=loop_render_func):')
-        else:
-            self.write(extended_loop and '):' or ':')
-
-        # tests in not extended loops become a continue
-        if not extended_loop and node.test is not None:
-            self.indent()
-            self.writeline('if not ')
-            self.visit(node.test, loop_frame)
-            self.write(':')
-            self.indent()
-            self.writeline('continue')
-            self.outdent(2)
-
-        self.indent()
-        self.blockvisit(node.body, loop_frame)
-        if node.else_:
-            self.writeline('%s = 0' % iteration_indicator)
-        self.outdent()
-
-        if node.else_:
-            self.writeline('if %s:' % iteration_indicator)
-            self.indent()
-            self.blockvisit(node.else_, loop_frame)
-            self.outdent()
-
-        # reset the aliases if there are any.
-        if not node.recursive:
-            self.pop_scope(aliases, loop_frame)
-
-        # if the node was recursive we have to return the buffer contents
-        # and start the iteration code
-        if node.recursive:
-            self.return_buffer_contents(loop_frame)
-            self.outdent()
-            self.start_write(frame, node)
-            self.write('loop(')
-            self.visit(node.iter, frame)
-            self.write(', loop)')
-            self.end_write(frame)
-
-    def visit_If(self, node, frame):
-        if_frame = frame.soft()
-        self.writeline('if ', node)
-        self.visit(node.test, if_frame)
-        self.write(':')
-        self.indent()
-        self.blockvisit(node.body, if_frame)
-        self.outdent()
-        if node.else_:
-            self.writeline('else:')
-            self.indent()
-            self.blockvisit(node.else_, if_frame)
-            self.outdent()
-
-    def visit_Macro(self, node, frame):
-        macro_frame = self.macro_body(node, frame)
-        self.newline()
-        if frame.toplevel:
-            if not node.name.startswith('_'):
-                self.write('context.exported_vars.add(%r)' % node.name)
-            self.writeline('context.vars[%r] = ' % node.name)
-        self.write('l_%s = ' % node.name)
-        self.macro_def(node, macro_frame)
-        frame.assigned_names.add(node.name)
-
-    def visit_CallBlock(self, node, frame):
-        children = node.iter_child_nodes(exclude=('call',))
-        call_frame = self.macro_body(node, frame, children)
-        self.writeline('caller = ')
-        self.macro_def(node, call_frame)
-        self.start_write(frame, node)
-        self.visit_Call(node.call, call_frame, forward_caller=True)
-        self.end_write(frame)
-
-    def visit_FilterBlock(self, node, frame):
-        filter_frame = frame.inner()
-        filter_frame.inspect(node.iter_child_nodes())
-        aliases = self.push_scope(filter_frame)
-        self.pull_locals(filter_frame)
-        self.buffer(filter_frame)
-        self.blockvisit(node.body, filter_frame)
-        self.start_write(frame, node)
-        self.visit_Filter(node.filter, filter_frame)
-        self.end_write(frame)
-        self.pop_scope(aliases, filter_frame)
-
-    def visit_ExprStmt(self, node, frame):
-        self.newline(node)
-        self.visit(node.node, frame)
-
-    def visit_Output(self, node, frame):
-        # if we have a known extends statement, we don't output anything
-        # if we are in a require_output_check section
-        if self.has_known_extends and frame.require_output_check:
-            return
-
-        if self.environment.finalize:
-            finalize = lambda x: unicode(self.environment.finalize(x))
-        else:
-            finalize = unicode
-
-        # if we are inside a frame that requires output checking, we do so
-        outdent_later = False
-        if frame.require_output_check:
-            self.writeline('if parent_template is None:')
-            self.indent()
-            outdent_later = True
-
-        # try to evaluate as many chunks as possible into a static
-        # string at compile time.
-        body = []
-        for child in node.nodes:
-            try:
-                const = child.as_const(frame.eval_ctx)
-            except nodes.Impossible:
-                body.append(child)
-                continue
-            # the frame can't be volatile here, becaus otherwise the
-            # as_const() function would raise an Impossible exception
-            # at that point.
-            try:
-                if frame.eval_ctx.autoescape:
-                    if hasattr(const, '__html__'):
-                        const = const.__html__()
-                    else:
-                        const = escape(const)
-                const = finalize(const)
-            except:
-                # if something goes wrong here we evaluate the node
-                # at runtime for easier debugging
-                body.append(child)
-                continue
-            if body and isinstance(body[-1], list):
-                body[-1].append(const)
-            else:
-                body.append([const])
-
-        # if we have less than 3 nodes or a buffer we yield or extend/append
-        if len(body) < 3 or frame.buffer is not None:
-            if frame.buffer is not None:
-                # for one item we append, for more we extend
-                if len(body) == 1:
-                    self.writeline('%s.append(' % frame.buffer)
-                else:
-                    self.writeline('%s.extend((' % frame.buffer)
-                self.indent()
-            for item in body:
-                if isinstance(item, list):
-                    val = repr(concat(item))
-                    if frame.buffer is None:
-                        self.writeline('yield ' + val)
-                    else:
-                        self.writeline(val + ', ')
-                else:
-                    if frame.buffer is None:
-                        self.writeline('yield ', item)
-                    else:
-                        self.newline(item)
-                    close = 1
-                    if frame.eval_ctx.volatile:
-                        self.write('(context.eval_ctx.autoescape and'
-                                   ' escape or to_string)(')
-                    elif frame.eval_ctx.autoescape:
-                        self.write('escape(')
-                    else:
-                        self.write('to_string(')
-                    if self.environment.finalize is not None:
-                        self.write('environment.finalize(')
-                        close += 1
-                    self.visit(item, frame)
-                    self.write(')' * close)
-                    if frame.buffer is not None:
-                        self.write(', ')
-            if frame.buffer is not None:
-                # close the open parentheses
-                self.outdent()
-                self.writeline(len(body) == 1 and ')' or '))')
-
-        # otherwise we create a format string as this is faster in that case
-        else:
-            format = []
-            arguments = []
-            for item in body:
-                if isinstance(item, list):
-                    format.append(concat(item).replace('%', '%%'))
-                else:
-                    format.append('%s')
-                    arguments.append(item)
-            self.writeline('yield ')
-            self.write(repr(concat(format)) + ' % (')
-            idx = -1
-            self.indent()
-            for argument in arguments:
-                self.newline(argument)
-                close = 0
-                if frame.eval_ctx.volatile:
-                    self.write('(context.eval_ctx.autoescape and'
-                               ' escape or to_string)(')
-                    close += 1
-                elif frame.eval_ctx.autoescape:
-                    self.write('escape(')
-                    close += 1
-                if self.environment.finalize is not None:
-                    self.write('environment.finalize(')
-                    close += 1
-                self.visit(argument, frame)
-                self.write(')' * close + ', ')
-            self.outdent()
-            self.writeline(')')
-
-        if outdent_later:
-            self.outdent()
-
-    def visit_Assign(self, node, frame):
-        self.newline(node)
-        # toplevel assignments however go into the local namespace and
-        # the current template's context.  We create a copy of the frame
-        # here and add a set so that the Name visitor can add the assigned
-        # names here.
-        if frame.toplevel:
-            assignment_frame = frame.copy()
-            assignment_frame.toplevel_assignments = set()
-        else:
-            assignment_frame = frame
-        self.visit(node.target, assignment_frame)
-        self.write(' = ')
-        self.visit(node.node, frame)
-
-        # make sure toplevel assignments are added to the context.
-        if frame.toplevel:
-            public_names = [x for x in assignment_frame.toplevel_assignments
-                            if not x.startswith('_')]
-            if len(assignment_frame.toplevel_assignments) == 1:
-                name = next(iter(assignment_frame.toplevel_assignments))
-                self.writeline('context.vars[%r] = l_%s' % (name, name))
-            else:
-                self.writeline('context.vars.update({')
-                for idx, name in enumerate(assignment_frame.toplevel_assignments):
-                    if idx:
-                        self.write(', ')
-                    self.write('%r: l_%s' % (name, name))
-                self.write('})')
-            if public_names:
-                if len(public_names) == 1:
-                    self.writeline('context.exported_vars.add(%r)' %
-                                   public_names[0])
-                else:
-                    self.writeline('context.exported_vars.update((%s))' %
-                                   ', '.join(map(repr, public_names)))
-
-    # -- Expression Visitors
-
-    def visit_Name(self, node, frame):
-        if node.ctx == 'store' and frame.toplevel:
-            frame.toplevel_assignments.add(node.name)
-        self.write('l_' + node.name)
-        frame.assigned_names.add(node.name)
-
-    def visit_Const(self, node, frame):
-        val = node.value
-        if isinstance(val, float):
-            self.write(str(val))
-        else:
-            self.write(repr(val))
-
-    def visit_TemplateData(self, node, frame):
-        try:
-            self.write(repr(node.as_const(frame.eval_ctx)))
-        except nodes.Impossible:
-            self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
-                       % node.data)
-
-    def visit_Tuple(self, node, frame):
-        self.write('(')
-        idx = -1
-        for idx, item in enumerate(node.items):
-            if idx:
-                self.write(', ')
-            self.visit(item, frame)
-        self.write(idx == 0 and ',)' or ')')
-
-    def visit_List(self, node, frame):
-        self.write('[')
-        for idx, item in enumerate(node.items):
-            if idx:
-                self.write(', ')
-            self.visit(item, frame)
-        self.write(']')
-
-    def visit_Dict(self, node, frame):
-        self.write('{')
-        for idx, item in enumerate(node.items):
-            if idx:
-                self.write(', ')
-            self.visit(item.key, frame)
-            self.write(': ')
-            self.visit(item.value, frame)
-        self.write('}')
-
-    def binop(operator):
-        def visitor(self, node, frame):
-            self.write('(')
-            self.visit(node.left, frame)
-            self.write(' %s ' % operator)
-            self.visit(node.right, frame)
-            self.write(')')
-        return visitor
-
-    def uaop(operator):
-        def visitor(self, node, frame):
-            self.write('(' + operator)
-            self.visit(node.node, frame)
-            self.write(')')
-        return visitor
-
-    visit_Add = binop('+')
-    visit_Sub = binop('-')
-    visit_Mul = binop('*')
-    visit_Div = binop('/')
-    visit_FloorDiv = binop('//')
-    visit_Pow = binop('**')
-    visit_Mod = binop('%')
-    visit_And = binop('and')
-    visit_Or = binop('or')
-    visit_Pos = uaop('+')
-    visit_Neg = uaop('-')
-    visit_Not = uaop('not ')
-    del binop, uaop
-
-    def visit_Concat(self, node, frame):
-        if frame.eval_ctx.volatile:
-            func_name = '(context.eval_ctx.volatile and' \
-                        ' markup_join or unicode_join)'
-        elif frame.eval_ctx.autoescape:
-            func_name = 'markup_join'
-        else:
-            func_name = 'unicode_join'
-        self.write('%s((' % func_name)
-        for arg in node.nodes:
-            self.visit(arg, frame)
-            self.write(', ')
-        self.write('))')
-
-    def visit_Compare(self, node, frame):
-        self.visit(node.expr, frame)
-        for op in node.ops:
-            self.visit(op, frame)
-
-    def visit_Operand(self, node, frame):
-        self.write(' %s ' % operators[node.op])
-        self.visit(node.expr, frame)
-
-    def visit_Getattr(self, node, frame):
-        self.write('environment.getattr(')
-        self.visit(node.node, frame)
-        self.write(', %r)' % node.attr)
-
-    def visit_Getitem(self, node, frame):
-        # slices bypass the environment getitem method.
-        if isinstance(node.arg, nodes.Slice):
-            self.visit(node.node, frame)
-            self.write('[')
-            self.visit(node.arg, frame)
-            self.write(']')
-        else:
-            self.write('environment.getitem(')
-            self.visit(node.node, frame)
-            self.write(', ')
-            self.visit(node.arg, frame)
-            self.write(')')
-
-    def visit_Slice(self, node, frame):
-        if node.start is not None:
-            self.visit(node.start, frame)
-        self.write(':')
-        if node.stop is not None:
-            self.visit(node.stop, frame)
-        if node.step is not None:
-            self.write(':')
-            self.visit(node.step, frame)
-
-    def visit_Filter(self, node, frame):
-        self.write(self.filters[node.name] + '(')
-        func = self.environment.filters.get(node.name)
-        if func is None:
-            self.fail('no filter named %r' % node.name, node.lineno)
-        if getattr(func, 'contextfilter', False):
-            self.write('context, ')
-        elif getattr(func, 'evalcontextfilter', False):
-            self.write('context.eval_ctx, ')
-        elif getattr(func, 'environmentfilter', False):
-            self.write('environment, ')
-
-        # if the filter node is None we are inside a filter block
-        # and want to write to the current buffer
-        if node.node is not None:
-            self.visit(node.node, frame)
-        elif frame.eval_ctx.volatile:
-            self.write('(context.eval_ctx.autoescape and'
-                       ' Markup(concat(%s)) or concat(%s))' %
-                       (frame.buffer, frame.buffer))
-        elif frame.eval_ctx.autoescape:
-            self.write('Markup(concat(%s))' % frame.buffer)
-        else:
-            self.write('concat(%s)' % frame.buffer)
-        self.signature(node, frame)
-        self.write(')')
-
-    def visit_Test(self, node, frame):
-        self.write(self.tests[node.name] + '(')
-        if node.name not in self.environment.tests:
-            self.fail('no test named %r' % node.name, node.lineno)
-        self.visit(node.node, frame)
-        self.signature(node, frame)
-        self.write(')')
-
-    def visit_CondExpr(self, node, frame):
-        def write_expr2():
-            if node.expr2 is not None:
-                return self.visit(node.expr2, frame)
-            self.write('environment.undefined(%r)' % ('the inline if-'
-                       'expression on %s evaluated to false and '
-                       'no else section was defined.' % self.position(node)))
-
-        if not have_condexpr:
-            self.write('((')
-            self.visit(node.test, frame)
-            self.write(') and (')
-            self.visit(node.expr1, frame)
-            self.write(',) or (')
-            write_expr2()
-            self.write(',))[0]')
-        else:
-            self.write('(')
-            self.visit(node.expr1, frame)
-            self.write(' if ')
-            self.visit(node.test, frame)
-            self.write(' else ')
-            write_expr2()
-            self.write(')')
-
-    def visit_Call(self, node, frame, forward_caller=False):
-        if self.environment.sandboxed:
-            self.write('environment.call(context, ')
-        else:
-            self.write('context.call(')
-        self.visit(node.node, frame)
-        extra_kwargs = forward_caller and {'caller': 'caller'} or None
-        self.signature(node, frame, extra_kwargs)
-        self.write(')')
-
-    def visit_Keyword(self, node, frame):
-        self.write(node.key + '=')
-        self.visit(node.value, frame)
-
-    # -- Unused nodes for extensions
-
-    def visit_MarkSafe(self, node, frame):
-        self.write('Markup(')
-        self.visit(node.expr, frame)
-        self.write(')')
-
-    def visit_MarkSafeIfAutoescape(self, node, frame):
-        self.write('(context.eval_ctx.autoescape and Markup or identity)(')
-        self.visit(node.expr, frame)
-        self.write(')')
-
-    def visit_EnvironmentAttribute(self, node, frame):
-        self.write('environment.' + node.name)
-
-    def visit_ExtensionAttribute(self, node, frame):
-        self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
-
-    def visit_ImportedName(self, node, frame):
-        self.write(self.import_aliases[node.importname])
-
-    def visit_InternalName(self, node, frame):
-        self.write(node.name)
-
-    def visit_ContextReference(self, node, frame):
-        self.write('context')
-
-    def visit_Continue(self, node, frame):
-        self.writeline('continue', node)
-
-    def visit_Break(self, node, frame):
-        self.writeline('break', node)
-
-    def visit_Scope(self, node, frame):
-        scope_frame = frame.inner()
-        scope_frame.inspect(node.iter_child_nodes())
-        aliases = self.push_scope(scope_frame)
-        self.pull_locals(scope_frame)
-        self.blockvisit(node.body, scope_frame)
-        self.pop_scope(aliases, scope_frame)
-
-    def visit_EvalContextModifier(self, node, frame):
-        for keyword in node.options:
-            self.writeline('context.eval_ctx.%s = ' % keyword.key)
-            self.visit(keyword.value, frame)
-            try:
-                val = keyword.value.as_const(frame.eval_ctx)
-            except nodes.Impossible:
-                frame.eval_ctx.volatile = True
-            else:
-                setattr(frame.eval_ctx, keyword.key, val)
-
-    def visit_ScopedEvalContextModifier(self, node, frame):
-        old_ctx_name = self.temporary_identifier()
-        safed_ctx = frame.eval_ctx.save()
-        self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
-        self.visit_EvalContextModifier(node, frame)
-        for child in node.body:
-            self.visit(child, frame)
-        frame.eval_ctx.revert(safed_ctx)
-        self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/constants.py b/ambari-common/src/main/python/jinja2/jinja2/constants.py
deleted file mode 100644
index cab203c..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/constants.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja.constants
-    ~~~~~~~~~~~~~~~
-
-    Various constants.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-#: list of lorem ipsum words used by the lipsum() helper function
-LOREM_IPSUM_WORDS = u'''\
-a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
-auctor augue bibendum blandit class commodo condimentum congue consectetuer
-consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
-diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
-elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
-faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
-hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
-justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
-luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
-mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
-nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
-penatibus per pharetra phasellus placerat platea porta porttitor posuere
-potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
-ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
-sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
-tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
-ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
-viverra volutpat vulputate'''

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/debug.py b/ambari-common/src/main/python/jinja2/jinja2/debug.py
deleted file mode 100644
index eb15456..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/debug.py
+++ /dev/null
@@ -1,308 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.debug
-    ~~~~~~~~~~~~
-
-    Implements the debug interface for Jinja.  This module does some pretty
-    ugly stuff with the Python traceback system in order to achieve tracebacks
-    with correct line numbers, locals and contents.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import sys
-import traceback
-from jinja2.utils import CodeType, missing, internal_code
-from jinja2.exceptions import TemplateSyntaxError
-
-
-# how does the raise helper look like?
-try:
-    exec "raise TypeError, 'foo'"
-except SyntaxError:
-    raise_helper = 'raise __jinja_exception__[1]'
-except TypeError:
-    raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]'
-
-
-class TracebackFrameProxy(object):
-    """Proxies a traceback frame."""
-
-    def __init__(self, tb):
-        self.tb = tb
-
-    def _set_tb_next(self, next):
-        if tb_set_next is not None:
-            tb_set_next(self.tb, next and next.tb or None)
-        self._tb_next = next
-
-    def _get_tb_next(self):
-        return self._tb_next
-
-    tb_next = property(_get_tb_next, _set_tb_next)
-    del _get_tb_next, _set_tb_next
-
-    @property
-    def is_jinja_frame(self):
-        return '__jinja_template__' in self.tb.tb_frame.f_globals
-
-    def __getattr__(self, name):
-        return getattr(self.tb, name)
-
-
-class ProcessedTraceback(object):
-    """Holds a Jinja preprocessed traceback for priting or reraising."""
-
-    def __init__(self, exc_type, exc_value, frames):
-        assert frames, 'no frames for this traceback?'
-        self.exc_type = exc_type
-        self.exc_value = exc_value
-        self.frames = frames
-
-    def chain_frames(self):
-        """Chains the frames.  Requires ctypes or the debugsupport extension."""
-        prev_tb = None
-        for tb in self.frames:
-            if prev_tb is not None:
-                prev_tb.tb_next = tb
-            prev_tb = tb
-        prev_tb.tb_next = None
-
-    def render_as_text(self, limit=None):
-        """Return a string with the traceback."""
-        lines = traceback.format_exception(self.exc_type, self.exc_value,
-                                           self.frames[0], limit=limit)
-        return ''.join(lines).rstrip()
-
-    def render_as_html(self, full=False):
-        """Return a unicode string with the traceback as rendered HTML."""
-        from jinja2.debugrenderer import render_traceback
-        return u'%s\n\n<!--\n%s\n-->' % (
-            render_traceback(self, full=full),
-            self.render_as_text().decode('utf-8', 'replace')
-        )
-
-    @property
-    def is_template_syntax_error(self):
-        """`True` if this is a template syntax error."""
-        return isinstance(self.exc_value, TemplateSyntaxError)
-
-    @property
-    def exc_info(self):
-        """Exception info tuple with a proxy around the frame objects."""
-        return self.exc_type, self.exc_value, self.frames[0]
-
-    @property
-    def standard_exc_info(self):
-        """Standard python exc_info for re-raising"""
-        return self.exc_type, self.exc_value, self.frames[0].tb
-
-
-def make_traceback(exc_info, source_hint=None):
-    """Creates a processed traceback object from the exc_info."""
-    exc_type, exc_value, tb = exc_info
-    if isinstance(exc_value, TemplateSyntaxError):
-        exc_info = translate_syntax_error(exc_value, source_hint)
-        initial_skip = 0
-    else:
-        initial_skip = 1
-    return translate_exception(exc_info, initial_skip)
-
-
-def translate_syntax_error(error, source=None):
-    """Rewrites a syntax error to please traceback systems."""
-    error.source = source
-    error.translated = True
-    exc_info = (error.__class__, error, None)
-    filename = error.filename
-    if filename is None:
-        filename = '<unknown>'
-    return fake_exc_info(exc_info, filename, error.lineno)
-
-
-def translate_exception(exc_info, initial_skip=0):
-    """If passed an exc_info it will automatically rewrite the exceptions
-    all the way down to the correct line numbers and frames.
-    """
-    tb = exc_info[2]
-    frames = []
-
-    # skip some internal frames if wanted
-    for x in xrange(initial_skip):
-        if tb is not None:
-            tb = tb.tb_next
-    initial_tb = tb
-
-    while tb is not None:
-        # skip frames decorated with @internalcode.  These are internal
-        # calls we can't avoid and that are useless in template debugging
-        # output.
-        if tb.tb_frame.f_code in internal_code:
-            tb = tb.tb_next
-            continue
-
-        # save a reference to the next frame if we override the current
-        # one with a faked one.
-        next = tb.tb_next
-
-        # fake template exceptions
-        template = tb.tb_frame.f_globals.get('__jinja_template__')
-        if template is not None:
-            lineno = template.get_corresponding_lineno(tb.tb_lineno)
-            tb = fake_exc_info(exc_info[:2] + (tb,), template.filename,
-                               lineno)[2]
-
-        frames.append(TracebackFrameProxy(tb))
-        tb = next
-
-    # if we don't have any exceptions in the frames left, we have to
-    # reraise it unchanged.
-    # XXX: can we backup here?  when could this happen?
-    if not frames:
-        raise exc_info[0], exc_info[1], exc_info[2]
-
-    traceback = ProcessedTraceback(exc_info[0], exc_info[1], frames)
-    if tb_set_next is not None:
-        traceback.chain_frames()
-    return traceback
-
-
-def fake_exc_info(exc_info, filename, lineno):
-    """Helper for `translate_exception`."""
-    exc_type, exc_value, tb = exc_info
-
-    # figure the real context out
-    if tb is not None:
-        real_locals = tb.tb_frame.f_locals.copy()
-        ctx = real_locals.get('context')
-        if ctx:
-            locals = ctx.get_all()
-        else:
-            locals = {}
-        for name, value in real_locals.iteritems():
-            if name.startswith('l_') and value is not missing:
-                locals[name[2:]] = value
-
-        # if there is a local called __jinja_exception__, we get
-        # rid of it to not break the debug functionality.
-        locals.pop('__jinja_exception__', None)
-    else:
-        locals = {}
-
-    # assamble fake globals we need
-    globals = {
-        '__name__':             filename,
-        '__file__':             filename,
-        '__jinja_exception__':  exc_info[:2],
-
-        # we don't want to keep the reference to the template around
-        # to not cause circular dependencies, but we mark it as Jinja
-        # frame for the ProcessedTraceback
-        '__jinja_template__':   None
-    }
-
-    # and fake the exception
-    code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec')
-
-    # if it's possible, change the name of the code.  This won't work
-    # on some python environments such as google appengine
-    try:
-        if tb is None:
-            location = 'template'
-        else:
-            function = tb.tb_frame.f_code.co_name
-            if function == 'root':
-                location = 'top-level template code'
-            elif function.startswith('block_'):
-                location = 'block "%s"' % function[6:]
-            else:
-                location = 'template'
-        code = CodeType(0, code.co_nlocals, code.co_stacksize,
-                        code.co_flags, code.co_code, code.co_consts,
-                        code.co_names, code.co_varnames, filename,
-                        location, code.co_firstlineno,
-                        code.co_lnotab, (), ())
-    except:
-        pass
-
-    # execute the code and catch the new traceback
-    try:
-        exec code in globals, locals
-    except:
-        exc_info = sys.exc_info()
-        new_tb = exc_info[2].tb_next
-
-    # return without this frame
-    return exc_info[:2] + (new_tb,)
-
-
-def _init_ugly_crap():
-    """This function implements a few ugly things so that we can patch the
-    traceback objects.  The function returned allows resetting `tb_next` on
-    any python traceback object.
-    """
-    import ctypes
-    from types import TracebackType
-
-    # figure out side of _Py_ssize_t
-    if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
-        _Py_ssize_t = ctypes.c_int64
-    else:
-        _Py_ssize_t = ctypes.c_int
-
-    # regular python
-    class _PyObject(ctypes.Structure):
-        pass
-    _PyObject._fields_ = [
-        ('ob_refcnt', _Py_ssize_t),
-        ('ob_type', ctypes.POINTER(_PyObject))
-    ]
-
-    # python with trace
-    if hasattr(sys, 'getobjects'):
-        class _PyObject(ctypes.Structure):
-            pass
-        _PyObject._fields_ = [
-            ('_ob_next', ctypes.POINTER(_PyObject)),
-            ('_ob_prev', ctypes.POINTER(_PyObject)),
-            ('ob_refcnt', _Py_ssize_t),
-            ('ob_type', ctypes.POINTER(_PyObject))
-        ]
-
-    class _Traceback(_PyObject):
-        pass
-    _Traceback._fields_ = [
-        ('tb_next', ctypes.POINTER(_Traceback)),
-        ('tb_frame', ctypes.POINTER(_PyObject)),
-        ('tb_lasti', ctypes.c_int),
-        ('tb_lineno', ctypes.c_int)
-    ]
-
-    def tb_set_next(tb, next):
-        """Set the tb_next attribute of a traceback object."""
-        if not (isinstance(tb, TracebackType) and
-                (next is None or isinstance(next, TracebackType))):
-            raise TypeError('tb_set_next arguments must be traceback objects')
-        obj = _Traceback.from_address(id(tb))
-        if tb.tb_next is not None:
-            old = _Traceback.from_address(id(tb.tb_next))
-            old.ob_refcnt -= 1
-        if next is None:
-            obj.tb_next = ctypes.POINTER(_Traceback)()
-        else:
-            next = _Traceback.from_address(id(next))
-            next.ob_refcnt += 1
-            obj.tb_next = ctypes.pointer(next)
-
-    return tb_set_next
-
-
-# try to get a tb_set_next implementation
-try:
-    from jinja2._debugsupport import tb_set_next
-except ImportError:
-    try:
-        tb_set_next = _init_ugly_crap()
-    except:
-        tb_set_next = None
-del _init_ugly_crap

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/defaults.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/defaults.py b/ambari-common/src/main/python/jinja2/jinja2/defaults.py
deleted file mode 100644
index d2d4544..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/defaults.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.defaults
-    ~~~~~~~~~~~~~~~
-
-    Jinja default filters and tags.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
-
-
-# defaults for the parser / lexer
-BLOCK_START_STRING = '{%'
-BLOCK_END_STRING = '%}'
-VARIABLE_START_STRING = '{{'
-VARIABLE_END_STRING = '}}'
-COMMENT_START_STRING = '{#'
-COMMENT_END_STRING = '#}'
-LINE_STATEMENT_PREFIX = None
-LINE_COMMENT_PREFIX = None
-TRIM_BLOCKS = False
-NEWLINE_SEQUENCE = '\n'
-
-
-# default filters, tests and namespace
-from jinja2.filters import FILTERS as DEFAULT_FILTERS
-from jinja2.tests import TESTS as DEFAULT_TESTS
-DEFAULT_NAMESPACE = {
-    'range':        xrange,
-    'dict':         lambda **kw: kw,
-    'lipsum':       generate_lorem_ipsum,
-    'cycler':       Cycler,
-    'joiner':       Joiner
-}
-
-
-# export all constants
-__all__ = tuple(x for x in locals().keys() if x.isupper())


[15/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py
deleted file mode 100644
index 69ff4bc..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py
+++ /dev/null
@@ -1,390 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.lexnparse
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    All the unittests regarding lexing, parsing and syntax.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import time
-import tempfile
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment, Template, TemplateSyntaxError, \
-     UndefinedError, nodes
-
-env = Environment()
-
-
-# how does a string look like in jinja syntax?
-if sys.version_info < (3, 0):
-    def jinja_string_repr(string):
-        return repr(string)[1:]
-else:
-    jinja_string_repr = repr
-
-
-class LexerTestCase(JinjaTestCase):
-
-    def test_raw1(self):
-        tmpl = env.from_string('{% raw %}foo{% endraw %}|'
-                               '{%raw%}{{ bar }}|{% baz %}{%       endraw    %}')
-        assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
-
-    def test_raw2(self):
-        tmpl = env.from_string('1  {%- raw -%}   2   {%- endraw -%}   3')
-        assert tmpl.render() == '123'
-
-    def test_balancing(self):
-        env = Environment('{%', '%}', '${', '}')
-        tmpl = env.from_string('''{% for item in seq
-            %}${{'foo': item}|upper}{% endfor %}''')
-        assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
-
-    def test_comments(self):
-        env = Environment('<!--', '-->', '{', '}')
-        tmpl = env.from_string('''\
-<ul>
-<!--- for item in seq -->
-  <li>{item}</li>
-<!--- endfor -->
-</ul>''')
-        assert tmpl.render(seq=range(3)) == ("<ul>\n  <li>0</li>\n  "
-                                             "<li>1</li>\n  <li>2</li>\n</ul>")
-
-    def test_string_escapes(self):
-        for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
-            tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
-            assert tmpl.render() == char
-        assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
-
-    def test_bytefallback(self):
-        from pprint import pformat
-        tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
-        assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
-
-    def test_operators(self):
-        from ambari_jinja2.lexer import operators
-        for test, expect in operators.iteritems():
-            if test in '([{}])':
-                continue
-            stream = env.lexer.tokenize('{{ %s }}' % test)
-            stream.next()
-            assert stream.current.type == expect
-
-    def test_normalizing(self):
-        for seq in '\r', '\r\n', '\n':
-            env = Environment(newline_sequence=seq)
-            tmpl = env.from_string('1\n2\r\n3\n4\n')
-            result = tmpl.render()
-            assert result.replace(seq, 'X') == '1X2X3X4'
-
-
-class ParserTestCase(JinjaTestCase):
-
-    def test_php_syntax(self):
-        env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
-        tmpl = env.from_string('''\
-<!-- I'm a comment, I'm not interesting -->\
-<? for item in seq -?>
-    <?= item ?>
-<?- endfor ?>''')
-        assert tmpl.render(seq=range(5)) == '01234'
-
-    def test_erb_syntax(self):
-        env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
-        tmpl = env.from_string('''\
-<%# I'm a comment, I'm not interesting %>\
-<% for item in seq -%>
-    <%= item %>
-<%- endfor %>''')
-        assert tmpl.render(seq=range(5)) == '01234'
-
-    def test_comment_syntax(self):
-        env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
-        tmpl = env.from_string('''\
-<!--# I'm a comment, I'm not interesting -->\
-<!-- for item in seq --->
-    ${item}
-<!--- endfor -->''')
-        assert tmpl.render(seq=range(5)) == '01234'
-
-    def test_balancing(self):
-        tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
-        assert tmpl.render() == 'bar'
-
-    def test_start_comment(self):
-        tmpl = env.from_string('''{# foo comment
-and bar comment #}
-{% macro blub() %}foo{% endmacro %}
-{{ blub() }}''')
-        assert tmpl.render().strip() == 'foo'
-
-    def test_line_syntax(self):
-        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
-        tmpl = env.from_string('''\
-<%# regular comment %>
-% for item in seq:
-    ${item}
-% endfor''')
-        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
-               range(5)
-
-        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
-        tmpl = env.from_string('''\
-<%# regular comment %>
-% for item in seq:
-    ${item} ## the rest of the stuff
-% endfor''')
-        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
-                range(5)
-
-    def test_line_syntax_priority(self):
-        # XXX: why is the whitespace there in front of the newline?
-        env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
-        tmpl = env.from_string('''\
-/* ignore me.
-   I'm a multiline comment */
-## for item in seq:
-* ${item}          # this is just extra stuff
-## endfor''')
-        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2'
-        env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##')
-        tmpl = env.from_string('''\
-/* ignore me.
-   I'm a multiline comment */
-# for item in seq:
-* ${item}          ## this is just extra stuff
-    ## extra stuff i just want to ignore
-# endfor''')
-        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
-
-    def test_error_messages(self):
-        def assert_error(code, expected):
-            try:
-                Template(code)
-            except TemplateSyntaxError, e:
-                assert str(e) == expected, 'unexpected error message'
-            else:
-                assert False, 'that was suposed to be an error'
-
-        assert_error('{% for item in seq %}...{% endif %}',
-                     "Encountered unknown tag 'endif'. Jinja was looking "
-                     "for the following tags: 'endfor' or 'else'. The "
-                     "innermost block that needs to be closed is 'for'.")
-        assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
-                     "Encountered unknown tag 'endfor'. Jinja was looking for "
-                     "the following tags: 'elif' or 'else' or 'endif'. The "
-                     "innermost block that needs to be closed is 'if'.")
-        assert_error('{% if foo %}',
-                     "Unexpected end of template. Jinja was looking for the "
-                     "following tags: 'elif' or 'else' or 'endif'. The "
-                     "innermost block that needs to be closed is 'if'.")
-        assert_error('{% for item in seq %}',
-                     "Unexpected end of template. Jinja was looking for the "
-                     "following tags: 'endfor' or 'else'. The innermost block "
-                     "that needs to be closed is 'for'.")
-        assert_error('{% block foo-bar-baz %}',
-                     "Block names in Jinja have to be valid Python identifiers "
-                     "and may not contain hypens, use an underscore instead.")
-        assert_error('{% unknown_tag %}',
-                     "Encountered unknown tag 'unknown_tag'.")
-
-
-class SyntaxTestCase(JinjaTestCase):
-
-    def test_call(self):
-        env = Environment()
-        env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
-        tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
-        assert tmpl.render() == 'abdfh'
-
-    def test_slicing(self):
-        tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
-        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
-
-    def test_attr(self):
-        tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
-        assert tmpl.render(foo={'bar': 42}) == '42|42'
-
-    def test_subscript(self):
-        tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
-        assert tmpl.render(foo=[0, 1, 2]) == '0|2'
-
-    def test_tuple(self):
-        tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
-        assert tmpl.render() == '()|(1,)|(1, 2)'
-
-    def test_math(self):
-        tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
-        assert tmpl.render() == '1.5|8'
-
-    def test_div(self):
-        tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
-        assert tmpl.render() == '1|1.5|1'
-
-    def test_unary(self):
-        tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
-        assert tmpl.render() == '3|-3'
-
-    def test_concat(self):
-        tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
-        assert tmpl.render() == '[1, 2]foo'
-
-    def test_compare(self):
-        tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
-                               '{{ 2 == 2 }}|{{ 1 <= 1 }}')
-        assert tmpl.render() == 'True|True|True|True|True'
-
-    def test_inop(self):
-        tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
-        assert tmpl.render() == 'True|False'
-
-    def test_literals(self):
-        tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
-        assert tmpl.render().lower() == '[]|{}|()'
-
-    def test_bool(self):
-        tmpl = env.from_string('{{ true and false }}|{{ false '
-                               'or true }}|{{ not false }}')
-        assert tmpl.render() == 'False|True|True'
-
-    def test_grouping(self):
-        tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
-        assert tmpl.render() == 'False'
-
-    def test_django_attr(self):
-        tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
-        assert tmpl.render() == '1|1'
-
-    def test_conditional_expression(self):
-        tmpl = env.from_string('''{{ 0 if true else 1 }}''')
-        assert tmpl.render() == '0'
-
-    def test_short_conditional_expression(self):
-        tmpl = env.from_string('<{{ 1 if false }}>')
-        assert tmpl.render() == '<>'
-
-        tmpl = env.from_string('<{{ (1 if false).bar }}>')
-        self.assert_raises(UndefinedError, tmpl.render)
-
-    def test_filter_priority(self):
-        tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
-        assert tmpl.render() == 'FOOBAR'
-
-    def test_function_calls(self):
-        tests = [
-            (True, '*foo, bar'),
-            (True, '*foo, *bar'),
-            (True, '*foo, bar=42'),
-            (True, '**foo, *bar'),
-            (True, '**foo, bar'),
-            (False, 'foo, bar'),
-            (False, 'foo, bar=42'),
-            (False, 'foo, bar=23, *args'),
-            (False, 'a, b=c, *d, **e'),
-            (False, '*foo, **bar')
-        ]
-        for should_fail, sig in tests:
-            if should_fail:
-                self.assert_raises(TemplateSyntaxError,
-                    env.from_string, '{{ foo(%s) }}' % sig)
-            else:
-                env.from_string('foo(%s)' % sig)
-
-    def test_tuple_expr(self):
-        for tmpl in [
-            '{{ () }}',
-            '{{ (1, 2) }}',
-            '{{ (1, 2,) }}',
-            '{{ 1, }}',
-            '{{ 1, 2 }}',
-            '{% for foo, bar in seq %}...{% endfor %}',
-            '{% for x in foo, bar %}...{% endfor %}',
-            '{% for x in foo, %}...{% endfor %}'
-        ]:
-            assert env.from_string(tmpl)
-
-    def test_trailing_comma(self):
-        tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
-        assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
-
-    def test_block_end_name(self):
-        env.from_string('{% block foo %}...{% endblock foo %}')
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{% block x %}{% endblock y %}')
-
-    def test_contant_casing(self):
-        for const in True, False, None:
-            tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
-                str(const), str(const).lower(), str(const).upper()
-            ))
-            assert tmpl.render() == '%s|%s|' % (const, const)
-
-    def test_test_chaining(self):
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{{ foo is string is sequence }}')
-        env.from_string('{{ 42 is string or 42 is number }}'
-            ).render() == 'True'
-
-    def test_string_concatenation(self):
-        tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
-        assert tmpl.render() == 'foobarbaz'
-
-    def test_notin(self):
-        bar = xrange(100)
-        tmpl = env.from_string('''{{ not 42 in bar }}''')
-        assert tmpl.render(bar=bar) == unicode(not 42 in bar)
-
-    def test_implicit_subscribed_tuple(self):
-        class Foo(object):
-            def __getitem__(self, x):
-                return x
-        t = env.from_string('{{ foo[1, 2] }}')
-        assert t.render(foo=Foo()) == u'(1, 2)'
-
-    def test_raw2(self):
-        tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
-        assert tmpl.render() == '{{ FOO }} and {% BAR %}'
-
-    def test_const(self):
-        tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
-                               '{{ none is defined }}|{{ missing is defined }}')
-        assert tmpl.render() == 'True|False|None|True|False'
-
-    def test_neg_filter_priority(self):
-        node = env.parse('{{ -1|foo }}')
-        assert isinstance(node.body[0].nodes[0], nodes.Filter)
-        assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
-
-    def test_const_assign(self):
-        constass1 = '''{% set true = 42 %}'''
-        constass2 = '''{% for none in seq %}{% endfor %}'''
-        for tmpl in constass1, constass2:
-            self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
-
-    def test_localset(self):
-        tmpl = env.from_string('''{% set foo = 0 %}\
-{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
-{{ foo }}''')
-        assert tmpl.render() == '0'
-
-    def test_parse_unary(self):
-        tmpl = env.from_string('{{ -foo["bar"] }}')
-        assert tmpl.render(foo={'bar': 42}) == '-42'
-        tmpl = env.from_string('{{ -foo["bar"]|abs }}')
-        assert tmpl.render(foo={'bar': 42}) == '42'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LexerTestCase))
-    suite.addTest(unittest.makeSuite(ParserTestCase))
-    suite.addTest(unittest.makeSuite(SyntaxTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py
deleted file mode 100644
index e133bd4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.loader
-    ~~~~~~~~~~~~~~~~~~~~~~~
-
-    Test the loaders.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import time
-import tempfile
-import shutil
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase, dict_loader, \
-     package_loader, filesystem_loader, function_loader, \
-     choice_loader, prefix_loader
-
-from ambari_jinja2 import Environment, loaders
-from ambari_jinja2.loaders import split_template_path
-from ambari_jinja2.exceptions import TemplateNotFound
-
-
-class LoaderTestCase(JinjaTestCase):
-
-    def test_dict_loader(self):
-        env = Environment(loader=dict_loader)
-        tmpl = env.get_template('justdict.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_package_loader(self):
-        env = Environment(loader=package_loader)
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_filesystem_loader(self):
-        env = Environment(loader=filesystem_loader)
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        tmpl = env.get_template('foo/test.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_choice_loader(self):
-        env = Environment(loader=choice_loader)
-        tmpl = env.get_template('justdict.html')
-        assert tmpl.render().strip() == 'FOO'
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_function_loader(self):
-        env = Environment(loader=function_loader)
-        tmpl = env.get_template('justfunction.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_prefix_loader(self):
-        env = Environment(loader=prefix_loader)
-        tmpl = env.get_template('a/test.html')
-        assert tmpl.render().strip() == 'BAR'
-        tmpl = env.get_template('b/justdict.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing')
-
-    def test_caching(self):
-        changed = False
-        class TestLoader(loaders.BaseLoader):
-            def get_source(self, environment, template):
-                return u'foo', None, lambda: not changed
-        env = Environment(loader=TestLoader(), cache_size=-1)
-        tmpl = env.get_template('template')
-        assert tmpl is env.get_template('template')
-        changed = True
-        assert tmpl is not env.get_template('template')
-        changed = False
-
-        env = Environment(loader=TestLoader(), cache_size=0)
-        assert env.get_template('template') \
-               is not env.get_template('template')
-
-        env = Environment(loader=TestLoader(), cache_size=2)
-        t1 = env.get_template('one')
-        t2 = env.get_template('two')
-        assert t2 is env.get_template('two')
-        assert t1 is env.get_template('one')
-        t3 = env.get_template('three')
-        assert 'one' in env.cache
-        assert 'two' not in env.cache
-        assert 'three' in env.cache
-
-    def test_split_template_path(self):
-        assert split_template_path('foo/bar') == ['foo', 'bar']
-        assert split_template_path('./foo/bar') == ['foo', 'bar']
-        self.assert_raises(TemplateNotFound, split_template_path, '../foo')
-
-
-class ModuleLoaderTestCase(JinjaTestCase):
-    archive = None
-
-    def compile_down(self, zip='deflated', py_compile=False):
-        super(ModuleLoaderTestCase, self).setup()
-        log = []
-        self.reg_env = Environment(loader=prefix_loader)
-        if zip is not None:
-            self.archive = tempfile.mkstemp(suffix='.zip')[1]
-        else:
-            self.archive = tempfile.mkdtemp()
-        self.reg_env.compile_templates(self.archive, zip=zip,
-                                       log_function=log.append,
-                                       py_compile=py_compile)
-        self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
-        return ''.join(log)
-
-    def teardown(self):
-        super(ModuleLoaderTestCase, self).teardown()
-        if hasattr(self, 'mod_env'):
-            if os.path.isfile(self.archive):
-                os.remove(self.archive)
-            else:
-                shutil.rmtree(self.archive)
-            self.archive = None
-
-    def test_log(self):
-        log = self.compile_down()
-        assert 'Compiled "a/foo/test.html" as ' \
-               'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
-        assert 'Finished compiling templates' in log
-        assert 'Could not compile "a/syntaxerror.html": ' \
-               'Encountered unknown tag \'endif\'' in log
-
-    def _test_common(self):
-        tmpl1 = self.reg_env.get_template('a/test.html')
-        tmpl2 = self.mod_env.get_template('a/test.html')
-        assert tmpl1.render() == tmpl2.render()
-
-        tmpl1 = self.reg_env.get_template('b/justdict.html')
-        tmpl2 = self.mod_env.get_template('b/justdict.html')
-        assert tmpl1.render() == tmpl2.render()
-
-    def test_deflated_zip_compile(self):
-        self.compile_down(zip='deflated')
-        self._test_common()
-
-    def test_stored_zip_compile(self):
-        self.compile_down(zip='stored')
-        self._test_common()
-
-    def test_filesystem_compile(self):
-        self.compile_down(zip=None)
-        self._test_common()
-
-    def test_weak_references(self):
-        self.compile_down()
-        tmpl = self.mod_env.get_template('a/test.html')
-        key = loaders.ModuleLoader.get_template_key('a/test.html')
-        name = self.mod_env.loader.module.__name__
-
-        assert hasattr(self.mod_env.loader.module, key)
-        assert name in sys.modules
-
-        # unset all, ensure the module is gone from sys.modules
-        self.mod_env = tmpl = None
-
-        try:
-            import gc
-            gc.collect()
-        except:
-            pass
-
-        assert name not in sys.modules
-
-    def test_byte_compilation(self):
-        log = self.compile_down(py_compile=True)
-        assert 'Byte-compiled "a/test.html"' in log
-        tmpl1 = self.mod_env.get_template('a/test.html')
-        mod = self.mod_env.loader.module. \
-            tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
-        assert mod.__file__.endswith('.pyc')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LoaderTestCase))
-    suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py
deleted file mode 100644
index b457df2..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.regression
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests corner cases and bugs.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
-     TemplateNotFound, PrefixLoader
-
-env = Environment()
-
-
-class CornerTestCase(JinjaTestCase):
-
-    def test_assigned_scoping(self):
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) -%}
-            [{{ item }}]
-        {%- endfor %}
-        {{- item -}}
-        ''')
-        assert t.render(item=42) == '[1][2][3][4]42'
-
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) -%}
-            [{{ item }}]
-        {%- endfor %}
-        {%- set item = 42 %}
-        {{- item -}}
-        ''')
-        assert t.render() == '[1][2][3][4]42'
-
-        t = env.from_string('''
-        {%- set item = 42 %}
-        {%- for item in (1, 2, 3, 4) -%}
-            [{{ item }}]
-        {%- endfor %}
-        {{- item -}}
-        ''')
-        assert t.render() == '[1][2][3][4]42'
-
-    def test_closure_scoping(self):
-        t = env.from_string('''
-        {%- set wrapper = "<FOO>" %}
-        {%- for item in (1, 2, 3, 4) %}
-            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
-            {{- wrapper() }}
-        {%- endfor %}
-        {{- wrapper -}}
-        ''')
-        assert t.render() == '[1][2][3][4]<FOO>'
-
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) %}
-            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
-            {{- wrapper() }}
-        {%- endfor %}
-        {%- set wrapper = "<FOO>" %}
-        {{- wrapper -}}
-        ''')
-        assert t.render() == '[1][2][3][4]<FOO>'
-
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) %}
-            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
-            {{- wrapper() }}
-        {%- endfor %}
-        {{- wrapper -}}
-        ''')
-        assert t.render(wrapper=23) == '[1][2][3][4]23'
-
-
-class BugTestCase(JinjaTestCase):
-
-    def test_keyword_folding(self):
-        env = Environment()
-        env.filters['testing'] = lambda value, some: value + some
-        assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
-               .render() == 'teststuff'
-
-    def test_extends_output_bugs(self):
-        env = Environment(loader=DictLoader({
-            'parent.html': '(({% block title %}{% endblock %}))'
-        }))
-
-        t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
-                            '[[{% block title %}title{% endblock %}]]'
-                            '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
-        assert t.render(expr=False) == '[[title]](1)(2)(3)'
-        assert t.render(expr=True) == '((title))'
-
-    def test_urlize_filter_escaping(self):
-        tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
-        assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">http://www.example.org/&lt;foo</a>'
-
-    def test_loop_call_loop(self):
-        tmpl = env.from_string('''
-
-        {% macro test() %}
-            {{ caller() }}
-        {% endmacro %}
-
-        {% for num1 in range(5) %}
-            {% call test() %}
-                {% for num2 in range(10) %}
-                    {{ loop.index }}
-                {% endfor %}
-            {% endcall %}
-        {% endfor %}
-
-        ''')
-
-        assert tmpl.render().split() == map(unicode, range(1, 11)) * 5
-
-    def test_weird_inline_comment(self):
-        env = Environment(line_statement_prefix='%')
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '% for item in seq {# missing #}\n...% endfor')
-
-    def test_old_macro_loop_scoping_bug(self):
-        tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
-                               '{% macro i() %}3{% endmacro %}{{ i() }}')
-        assert tmpl.render() == '123'
-
-    def test_partial_conditional_assignments(self):
-        tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
-        assert tmpl.render(a=23) == '23'
-        assert tmpl.render(b=True) == '42'
-
-    def test_stacked_locals_scoping_bug(self):
-        env = Environment(line_statement_prefix='#')
-        t = env.from_string('''\
-# for j in [1, 2]:
-#   set x = 1
-#   for i in [1, 2]:
-#     print x
-#     if i % 2 == 0:
-#       set x = x + 1
-#     endif
-#   endfor
-# endfor
-# if a
-#   print 'A'
-# elif b
-#   print 'B'
-# elif c == d
-#   print 'C'
-# else
-#   print 'D'
-# endif
-    ''')
-        assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
-
-    def test_stacked_locals_scoping_bug_twoframe(self):
-        t = Template('''
-            {% set x = 1 %}
-            {% for item in foo %}
-                {% if item == 1 %}
-                    {% set x = 2 %}
-                {% endif %}
-            {% endfor %}
-            {{ x }}
-        ''')
-        rv = t.render(foo=[1]).strip()
-        assert rv == u'1'
-
-    def test_call_with_args(self):
-        t = Template("""{% macro dump_users(users) -%}
-        <ul>
-          {%- for user in users -%}
-            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
-          {%- endfor -%}
-          </ul>
-        {%- endmacro -%}
-
-        {% call(user) dump_users(list_of_user) -%}
-          <dl>
-            <dl>Realname</dl>
-            <dd>{{ user.realname|e }}</dd>
-            <dl>Description</dl>
-            <dd>{{ user.description }}</dd>
-          </dl>
-        {% endcall %}""")
-
-        assert [x.strip() for x in t.render(list_of_user=[{
-            'username':'apo',
-            'realname':'something else',
-            'description':'test'
-        }]).splitlines()] == [
-            u'<ul><li><p>apo</p><dl>',
-            u'<dl>Realname</dl>',
-            u'<dd>something else</dd>',
-            u'<dl>Description</dl>',
-            u'<dd>test</dd>',
-            u'</dl>',
-            u'</li></ul>'
-        ]
-
-    def test_empty_if_condition_fails(self):
-        self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
-        self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
-        self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
-
-    def test_recursive_loop_bug(self):
-        tpl1 = Template("""
-        {% for p in foo recursive%}
-            {{p.bar}}
-            {% for f in p.fields recursive%}
-                {{f.baz}}
-                {{p.bar}}
-                {% if f.rec %}
-                    {{ loop(f.sub) }}
-                {% endif %}
-            {% endfor %}
-        {% endfor %}
-        """)
-
-        tpl2 = Template("""
-        {% for p in foo%}
-            {{p.bar}}
-            {% for f in p.fields recursive%}
-                {{f.baz}}
-                {{p.bar}}
-                {% if f.rec %}
-                    {{ loop(f.sub) }}
-                {% endif %}
-            {% endfor %}
-        {% endfor %}
-        """)
-
-    def test_correct_prefix_loader_name(self):
-        env = Environment(loader=PrefixLoader({
-            'foo':  DictLoader({})
-        }))
-        try:
-            env.get_template('foo/bar.html')
-        except TemplateNotFound, e:
-            assert e.name == 'foo/bar.html'
-        else:
-            assert False, 'expected error here'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(CornerTestCase))
-    suite.addTest(unittest.makeSuite(BugTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html
deleted file mode 100644
index 77669fa..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html
+++ /dev/null
@@ -1,3 +0,0 @@
-Before
-{{ fail() }}
-After

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html
deleted file mode 100644
index b7d6715..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html
+++ /dev/null
@@ -1 +0,0 @@
-FOO

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html
deleted file mode 100644
index f21b817..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html
+++ /dev/null
@@ -1,4 +0,0 @@
-Foo
-{% for item in broken %}
-  ...
-{% endif %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html
deleted file mode 100644
index ba578e4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html
+++ /dev/null
@@ -1 +0,0 @@
-BAR

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py
deleted file mode 100644
index 893526d..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.security
-    ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Checks the sandbox and other security features.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment
-from ambari_jinja2.sandbox import SandboxedEnvironment, \
-     ImmutableSandboxedEnvironment, unsafe
-from ambari_jinja2 import Markup, escape
-from ambari_jinja2.exceptions import SecurityError, TemplateSyntaxError
-
-
-class PrivateStuff(object):
-
-    def bar(self):
-        return 23
-
-    @unsafe
-    def foo(self):
-        return 42
-
-    def __repr__(self):
-        return 'PrivateStuff'
-
-
-class PublicStuff(object):
-    bar = lambda self: 23
-    _foo = lambda self: 42
-
-    def __repr__(self):
-        return 'PublicStuff'
-
-
-class SandboxTestCase(JinjaTestCase):
-
-    def test_unsafe(self):
-        env = SandboxedEnvironment()
-        self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
-                           foo=PrivateStuff())
-        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
-
-        self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
-                           foo=PublicStuff())
-        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
-        self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
-        self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
-        self.assert_raises(SecurityError, env.from_string(
-            "{{ foo.__class__.__subclasses__() }}").render, foo=42)
-
-    def test_immutable_environment(self):
-        env = ImmutableSandboxedEnvironment()
-        self.assert_raises(SecurityError, env.from_string(
-            '{{ [].append(23) }}').render)
-        self.assert_raises(SecurityError, env.from_string(
-            '{{ {1:2}.clear() }}').render)
-
-    def test_restricted(self):
-        env = SandboxedEnvironment()
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                      "{% for item.attribute in seq %}...{% endfor %}")
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                      "{% for foo, bar.baz in seq %}...{% endfor %}")
-
-    def test_markup_operations(self):
-        # adding two strings should escape the unsafe one
-        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
-        safe = Markup('<em>username</em>')
-        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
-
-        # string interpolations are safe to use too
-        assert Markup('<em>%s</em>') % '<bad user>' == \
-               '<em>&lt;bad user&gt;</em>'
-        assert Markup('<em>%(username)s</em>') % {
-            'username': '<bad user>'
-        } == '<em>&lt;bad user&gt;</em>'
-
-        # an escaped object is markup too
-        assert type(Markup('foo') + 'bar') is Markup
-
-        # and it implements __html__ by returning itself
-        x = Markup("foo")
-        assert x.__html__() is x
-
-        # it also knows how to treat __html__ objects
-        class Foo(object):
-            def __html__(self):
-                return '<em>awesome</em>'
-            def __unicode__(self):
-                return 'awesome'
-        assert Markup(Foo()) == '<em>awesome</em>'
-        assert Markup('<strong>%s</strong>') % Foo() == \
-               '<strong><em>awesome</em></strong>'
-
-        # escaping and unescaping
-        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
-        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
-        assert Markup("&lt;test&gt;").unescape() == "<test>"
-
-
-    def test_template_data(self):
-        env = Environment(autoescape=True)
-        t = env.from_string('{% macro say_hello(name) %}'
-                            '<p>Hello {{ name }}!</p>{% endmacro %}'
-                            '{{ say_hello("<blink>foo</blink>") }}')
-        escaped_out = '<p>Hello &lt;blink&gt;foo&lt;/blink&gt;!</p>'
-        assert t.render() == escaped_out
-        assert unicode(t.module) == escaped_out
-        assert escape(t.module) == escaped_out
-        assert t.module.say_hello('<blink>foo</blink>') == escaped_out
-        assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
-
-
-    def test_attr_filter(self):
-        env = SandboxedEnvironment()
-        tmpl = env.from_string('{{ 42|attr("__class__")|attr("__subclasses__")() }}')
-        self.assert_raises(SecurityError, tmpl.render)
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(SandboxTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py
deleted file mode 100644
index 2f7b792..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.tests
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Who tests the tests?
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Markup, Environment
-
-env = Environment()
-
-
-class TestsTestCase(JinjaTestCase):
-
-    def test_defined(self):
-        tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
-        assert tmpl.render() == 'False|True'
-
-    def test_even(self):
-        tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
-        assert tmpl.render() == 'False|True'
-
-    def test_odd(self):
-        tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
-        assert tmpl.render() == 'True|False'
-
-    def test_lower(self):
-        tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
-        assert tmpl.render() == 'True|False'
-
-    def test_typechecks(self):
-        tmpl = env.from_string('''
-            {{ 42 is undefined }}
-            {{ 42 is defined }}
-            {{ 42 is none }}
-            {{ none is none }}
-            {{ 42 is number }}
-            {{ 42 is string }}
-            {{ "foo" is string }}
-            {{ "foo" is sequence }}
-            {{ [1] is sequence }}
-            {{ range is callable }}
-            {{ 42 is callable }}
-            {{ range(5) is iterable }}
-        ''')
-        assert tmpl.render().split() == [
-            'False', 'True', 'False', 'True', 'True', 'False',
-            'True', 'True', 'True', 'True', 'False', 'True'
-        ]
-
-    def test_sequence(self):
-        tmpl = env.from_string(
-            '{{ [1, 2, 3] is sequence }}|'
-            '{{ "foo" is sequence }}|'
-            '{{ 42 is sequence }}'
-        )
-        assert tmpl.render() == 'True|True|False'
-
-    def test_upper(self):
-        tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
-        assert tmpl.render() == 'True|False'
-
-    def test_sameas(self):
-        tmpl = env.from_string('{{ foo is sameas false }}|'
-                               '{{ 0 is sameas false }}')
-        assert tmpl.render(foo=False) == 'True|False'
-
-    def test_no_paren_for_arg1(self):
-        tmpl = env.from_string('{{ foo is sameas none }}')
-        assert tmpl.render(foo=None) == 'True'
-
-    def test_escaped(self):
-        env = Environment(autoescape=True)
-        tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
-        assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(TestsTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py
deleted file mode 100644
index 297ba6a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.utils
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests utilities jinja uses.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import gc
-import unittest
-
-import pickle
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment, Undefined, DebugUndefined, \
-     StrictUndefined, UndefinedError, Template, meta
-from ambari_jinja2.utils import LRUCache, escape, object_type_repr
-
-
-class LRUCacheTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        d = LRUCache(3)
-        d["a"] = 1
-        d["b"] = 2
-        d["c"] = 3
-        d["a"]
-        d["d"] = 4
-        assert len(d) == 3
-        assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d
-
-    def test_pickleable(self):
-        cache = LRUCache(2)
-        cache["foo"] = 42
-        cache["bar"] = 23
-        cache["foo"]
-
-        for protocol in range(3):
-            copy = pickle.loads(pickle.dumps(cache, protocol))
-            assert copy.capacity == cache.capacity
-            assert copy._mapping == cache._mapping
-            assert copy._queue == cache._queue
-
-
-class HelpersTestCase(JinjaTestCase):
-
-    def test_object_type_repr(self):
-        class X(object):
-            pass
-        self.assert_equal(object_type_repr(42), 'int object')
-        self.assert_equal(object_type_repr([]), 'list object')
-        self.assert_equal(object_type_repr(X()),
-                         'ambari_jinja2.testsuite.utils.X object')
-        self.assert_equal(object_type_repr(None), 'None')
-        self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
-
-
-class MarkupLeakTestCase(JinjaTestCase):
-
-    def test_markup_leaks(self):
-        counts = set()
-        for count in xrange(20):
-            for item in xrange(1000):
-                escape("foo")
-                escape("<foo>")
-                escape(u"foo")
-                escape(u"<foo>")
-            counts.add(len(gc.get_objects()))
-        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LRUCacheTestCase))
-    suite.addTest(unittest.makeSuite(HelpersTestCase))
-
-    # this test only tests the c extension
-    if not hasattr(escape, 'func_code'):
-        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
-
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py
deleted file mode 100644
index bd3c0b4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py
+++ /dev/null
@@ -1,601 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.utils
-    ~~~~~~~~~~~~
-
-    Utility functions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import sys
-import errno
-try:
-    from thread import allocate_lock
-except ImportError:
-    from dummy_thread import allocate_lock
-from collections import deque
-from itertools import imap
-
-
-_word_split_re = re.compile(r'(\s+)')
-_punctuation_re = re.compile(
-    '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
-        '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
-        '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
-    )
-)
-_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
-_entity_re = re.compile(r'&([^;]+);')
-_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
-_digits = '0123456789'
-
-# special singleton representing missing values for the runtime
-missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
-
-# internal code
-internal_code = set()
-
-
-# concatenate a list of strings and convert them to unicode.
-# unfortunately there is a bug in python 2.4 and lower that causes
-# unicode.join trash the traceback.
-_concat = u''.join
-try:
-    def _test_gen_bug():
-        raise TypeError(_test_gen_bug)
-        yield None
-    _concat(_test_gen_bug())
-except TypeError, _error:
-    if not _error.args or _error.args[0] is not _test_gen_bug:
-        def concat(gen):
-            try:
-                return _concat(list(gen))
-            except:
-                # this hack is needed so that the current frame
-                # does not show up in the traceback.
-                exc_type, exc_value, tb = sys.exc_info()
-                raise exc_type, exc_value, tb.tb_next
-    else:
-        concat = _concat
-    del _test_gen_bug, _error
-
-
-# for python 2.x we create outselves a next() function that does the
-# basics without exception catching.
-try:
-    next = next
-except NameError:
-    def next(x):
-        return x.next()
-
-
-# if this python version is unable to deal with unicode filenames
-# when passed to encode we let this function encode it properly.
-# This is used in a couple of places.  As far as Jinja is concerned
-# filenames are unicode *or* bytestrings in 2.x and unicode only in
-# 3.x because compile cannot handle bytes
-if sys.version_info < (3, 0):
-    def _encode_filename(filename):
-        if isinstance(filename, unicode):
-            return filename.encode('utf-8')
-        return filename
-else:
-    def _encode_filename(filename):
-        assert filename is None or isinstance(filename, str), \
-            'filenames must be strings'
-        return filename
-
-from keyword import iskeyword as is_python_keyword
-
-
-# common types.  These do exist in the special types module too which however
-# does not exist in IronPython out of the box.  Also that way we don't have
-# to deal with implementation specific stuff here
-class _C(object):
-    def method(self): pass
-def _func():
-    yield None
-FunctionType = type(_func)
-GeneratorType = type(_func())
-MethodType = type(_C.method)
-CodeType = type(_C.method.func_code)
-try:
-    raise TypeError()
-except TypeError:
-    _tb = sys.exc_info()[2]
-    TracebackType = type(_tb)
-    FrameType = type(_tb.tb_frame)
-del _C, _tb, _func
-
-
-def contextfunction(f):
-    """This decorator can be used to mark a function or method context callable.
-    A context callable is passed the active :class:`Context` as first argument when
-    called from the template.  This is useful if a function wants to get access
-    to the context or functions provided on the context object.  For example
-    a function that returns a sorted list of template variables the current
-    template exports could look like this::
-
-        @contextfunction
-        def get_exported_names(context):
-            return sorted(context.exported_vars)
-    """
-    f.contextfunction = True
-    return f
-
-
-def evalcontextfunction(f):
-    """This decoraotr can be used to mark a function or method as an eval
-    context callable.  This is similar to the :func:`contextfunction`
-    but instead of passing the context, an evaluation context object is
-    passed.  For more information about the eval context, see
-    :ref:`eval-context`.
-
-    .. versionadded:: 2.4
-    """
-    f.evalcontextfunction = True
-    return f
-
-
-def environmentfunction(f):
-    """This decorator can be used to mark a function or method as environment
-    callable.  This decorator works exactly like the :func:`contextfunction`
-    decorator just that the first argument is the active :class:`Environment`
-    and not context.
-    """
-    f.environmentfunction = True
-    return f
-
-
-def internalcode(f):
-    """Marks the function as internally used"""
-    internal_code.add(f.func_code)
-    return f
-
-
-def is_undefined(obj):
-    """Check if the object passed is undefined.  This does nothing more than
-    performing an instance check against :class:`Undefined` but looks nicer.
-    This can be used for custom filters or tests that want to react to
-    undefined variables.  For example a custom default filter can look like
-    this::
-
-        def default(var, default=''):
-            if is_undefined(var):
-                return default
-            return var
-    """
-    from ambari_jinja2.runtime import Undefined
-    return isinstance(obj, Undefined)
-
-
-def consume(iterable):
-    """Consumes an iterable without doing anything with it."""
-    for event in iterable:
-        pass
-
-
-def clear_caches():
-    """Jinja2 keeps internal caches for environments and lexers.  These are
-    used so that Jinja2 doesn't have to recreate environments and lexers all
-    the time.  Normally you don't have to care about that but if you are
-    messuring memory consumption you may want to clean the caches.
-    """
-    from ambari_jinja2.environment import _spontaneous_environments
-    from ambari_jinja2.lexer import _lexer_cache
-    _spontaneous_environments.clear()
-    _lexer_cache.clear()
-
-
-def import_string(import_name, silent=False):
-    """Imports an object based on a string.  This use useful if you want to
-    use import paths as endpoints or something similar.  An import path can
-    be specified either in dotted notation (``xml.sax.saxutils.escape``)
-    or with a colon as object delimiter (``xml.sax.saxutils:escape``).
-
-    If the `silent` is True the return value will be `None` if the import
-    fails.
-
-    :return: imported object
-    """
-    try:
-        if ':' in import_name:
-            module, obj = import_name.split(':', 1)
-        elif '.' in import_name:
-            items = import_name.split('.')
-            module = '.'.join(items[:-1])
-            obj = items[-1]
-        else:
-            return __import__(import_name)
-        return getattr(__import__(module, None, None, [obj]), obj)
-    except (ImportError, AttributeError):
-        if not silent:
-            raise
-
-
-def open_if_exists(filename, mode='rb'):
-    """Returns a file descriptor for the filename if that file exists,
-    otherwise `None`.
-    """
-    try:
-        return open(filename, mode)
-    except IOError, e:
-        if e.errno not in (errno.ENOENT, errno.EISDIR):
-            raise
-
-
-def object_type_repr(obj):
-    """Returns the name of the object's type.  For some recognized
-    singletons the name of the object is returned instead. (For
-    example for `None` and `Ellipsis`).
-    """
-    if obj is None:
-        return 'None'
-    elif obj is Ellipsis:
-        return 'Ellipsis'
-    # __builtin__ in 2.x, builtins in 3.x
-    if obj.__class__.__module__ in ('__builtin__', 'builtins'):
-        name = obj.__class__.__name__
-    else:
-        name = obj.__class__.__module__ + '.' + obj.__class__.__name__
-    return '%s object' % name
-
-
-def pformat(obj, verbose=False):
-    """Prettyprint an object.  Either use the `pretty` library or the
-    builtin `pprint`.
-    """
-    try:
-        from pretty import pretty
-        return pretty(obj, verbose=verbose)
-    except ImportError:
-        from pprint import pformat
-        return pformat(obj)
-
-
-def urlize(text, trim_url_limit=None, nofollow=False):
-    """Converts any URLs in text into clickable links. Works on http://,
-    https:// and www. links. Links can have trailing punctuation (periods,
-    commas, close-parens) and leading punctuation (opening parens) and
-    it'll still do the right thing.
-
-    If trim_url_limit is not None, the URLs in link text will be limited
-    to trim_url_limit characters.
-
-    If nofollow is True, the URLs in link text will get a rel="nofollow"
-    attribute.
-    """
-    trim_url = lambda x, limit=trim_url_limit: limit is not None \
-                         and (x[:limit] + (len(x) >=limit and '...'
-                         or '')) or x
-    words = _word_split_re.split(unicode(escape(text)))
-    nofollow_attr = nofollow and ' rel="nofollow"' or ''
-    for i, word in enumerate(words):
-        match = _punctuation_re.match(word)
-        if match:
-            lead, middle, trail = match.groups()
-            if middle.startswith('www.') or (
-                '@' not in middle and
-                not middle.startswith('http://') and
-                len(middle) > 0 and
-                middle[0] in _letters + _digits and (
-                    middle.endswith('.org') or
-                    middle.endswith('.net') or
-                    middle.endswith('.com')
-                )):
-                middle = '<a href="http://%s"%s>%s</a>' % (middle,
-                    nofollow_attr, trim_url(middle))
-            if middle.startswith('http://') or \
-               middle.startswith('https://'):
-                middle = '<a href="%s"%s>%s</a>' % (middle,
-                    nofollow_attr, trim_url(middle))
-            if '@' in middle and not middle.startswith('www.') and \
-               not ':' in middle and _simple_email_re.match(middle):
-                middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
-            if lead + middle + trail != word:
-                words[i] = lead + middle + trail
-    return u''.join(words)
-
-
-def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
-    """Generate some lorem impsum for the template."""
-    from ambari_jinja2.constants import LOREM_IPSUM_WORDS
-    from random import choice, randrange
-    words = LOREM_IPSUM_WORDS.split()
-    result = []
-
-    for _ in xrange(n):
-        next_capitalized = True
-        last_comma = last_fullstop = 0
-        word = None
-        last = None
-        p = []
-
-        # each paragraph contains out of 20 to 100 words.
-        for idx, _ in enumerate(xrange(randrange(min, max))):
-            while True:
-                word = choice(words)
-                if word != last:
-                    last = word
-                    break
-            if next_capitalized:
-                word = word.capitalize()
-                next_capitalized = False
-            # add commas
-            if idx - randrange(3, 8) > last_comma:
-                last_comma = idx
-                last_fullstop += 2
-                word += ','
-            # add end of sentences
-            if idx - randrange(10, 20) > last_fullstop:
-                last_comma = last_fullstop = idx
-                word += '.'
-                next_capitalized = True
-            p.append(word)
-
-        # ensure that the paragraph ends with a dot.
-        p = u' '.join(p)
-        if p.endswith(','):
-            p = p[:-1] + '.'
-        elif not p.endswith('.'):
-            p += '.'
-        result.append(p)
-
-    if not html:
-        return u'\n\n'.join(result)
-    return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
-
-
-class LRUCache(object):
-    """A simple LRU Cache implementation."""
-
-    # this is fast for small capacities (something below 1000) but doesn't
-    # scale.  But as long as it's only used as storage for templates this
-    # won't do any harm.
-
-    def __init__(self, capacity):
-        self.capacity = capacity
-        self._mapping = {}
-        self._queue = deque()
-        self._postinit()
-
-    def _postinit(self):
-        # alias all queue methods for faster lookup
-        self._popleft = self._queue.popleft
-        self._pop = self._queue.pop
-        if hasattr(self._queue, 'remove'):
-            self._remove = self._queue.remove
-        self._wlock = allocate_lock()
-        self._append = self._queue.append
-
-    def _remove(self, obj):
-        """Python 2.4 compatibility."""
-        for idx, item in enumerate(self._queue):
-            if item == obj:
-                del self._queue[idx]
-                break
-
-    def __getstate__(self):
-        return {
-            'capacity':     self.capacity,
-            '_mapping':     self._mapping,
-            '_queue':       self._queue
-        }
-
-    def __setstate__(self, d):
-        self.__dict__.update(d)
-        self._postinit()
-
-    def __getnewargs__(self):
-        return (self.capacity,)
-
-    def copy(self):
-        """Return an shallow copy of the instance."""
-        rv = self.__class__(self.capacity)
-        rv._mapping.update(self._mapping)
-        rv._queue = deque(self._queue)
-        return rv
-
-    def get(self, key, default=None):
-        """Return an item from the cache dict or `default`"""
-        try:
-            return self[key]
-        except KeyError:
-            return default
-
-    def setdefault(self, key, default=None):
-        """Set `default` if the key is not in the cache otherwise
-        leave unchanged. Return the value of this key.
-        """
-        try:
-            return self[key]
-        except KeyError:
-            self[key] = default
-            return default
-
-    def clear(self):
-        """Clear the cache."""
-        self._wlock.acquire()
-        try:
-            self._mapping.clear()
-            self._queue.clear()
-        finally:
-            self._wlock.release()
-
-    def __contains__(self, key):
-        """Check if a key exists in this cache."""
-        return key in self._mapping
-
-    def __len__(self):
-        """Return the current size of the cache."""
-        return len(self._mapping)
-
-    def __repr__(self):
-        return '<%s %r>' % (
-            self.__class__.__name__,
-            self._mapping
-        )
-
-    def __getitem__(self, key):
-        """Get an item from the cache. Moves the item up so that it has the
-        highest priority then.
-
-        Raise an `KeyError` if it does not exist.
-        """
-        rv = self._mapping[key]
-        if self._queue[-1] != key:
-            try:
-                self._remove(key)
-            except ValueError:
-                # if something removed the key from the container
-                # when we read, ignore the ValueError that we would
-                # get otherwise.
-                pass
-            self._append(key)
-        return rv
-
-    def __setitem__(self, key, value):
-        """Sets the value for an item. Moves the item up so that it
-        has the highest priority then.
-        """
-        self._wlock.acquire()
-        try:
-            if key in self._mapping:
-                try:
-                    self._remove(key)
-                except ValueError:
-                    # __getitem__ is not locked, it might happen
-                    pass
-            elif len(self._mapping) == self.capacity:
-                del self._mapping[self._popleft()]
-            self._append(key)
-            self._mapping[key] = value
-        finally:
-            self._wlock.release()
-
-    def __delitem__(self, key):
-        """Remove an item from the cache dict.
-        Raise an `KeyError` if it does not exist.
-        """
-        self._wlock.acquire()
-        try:
-            del self._mapping[key]
-            try:
-                self._remove(key)
-            except ValueError:
-                # __getitem__ is not locked, it might happen
-                pass
-        finally:
-            self._wlock.release()
-
-    def items(self):
-        """Return a list of items."""
-        result = [(key, self._mapping[key]) for key in list(self._queue)]
-        result.reverse()
-        return result
-
-    def iteritems(self):
-        """Iterate over all items."""
-        return iter(self.items())
-
-    def values(self):
-        """Return a list of all values."""
-        return [x[1] for x in self.items()]
-
-    def itervalue(self):
-        """Iterate over all values."""
-        return iter(self.values())
-
-    def keys(self):
-        """Return a list of all keys ordered by most recent usage."""
-        return list(self)
-
-    def iterkeys(self):
-        """Iterate over all keys in the cache dict, ordered by
-        the most recent usage.
-        """
-        return reversed(tuple(self._queue))
-
-    __iter__ = iterkeys
-
-    def __reversed__(self):
-        """Iterate over the values in the cache dict, oldest items
-        coming first.
-        """
-        return iter(tuple(self._queue))
-
-    __copy__ = copy
-
-
-# register the LRU cache as mutable mapping if possible
-try:
-    from collections import MutableMapping
-    MutableMapping.register(LRUCache)
-except ImportError:
-    pass
-
-
-class Cycler(object):
-    """A cycle helper for templates."""
-
-    def __init__(self, *items):
-        if not items:
-            raise RuntimeError('at least one item has to be provided')
-        self.items = items
-        self.reset()
-
-    def reset(self):
-        """Resets the cycle."""
-        self.pos = 0
-
-    @property
-    def current(self):
-        """Returns the current item."""
-        return self.items[self.pos]
-
-    def next(self):
-        """Goes one item ahead and returns it."""
-        rv = self.current
-        self.pos = (self.pos + 1) % len(self.items)
-        return rv
-
-
-class Joiner(object):
-    """A joining helper for templates."""
-
-    def __init__(self, sep=u', '):
-        self.sep = sep
-        self.used = False
-
-    def __call__(self):
-        if not self.used:
-            self.used = True
-            return u''
-        return self.sep
-
-
-# try markupsafe first, if that fails go with Jinja2's bundled version
-# of markupsafe.  Markupsafe was previously Jinja2's implementation of
-# the Markup object but was moved into a separate package in a patchleve
-# release
-try:
-    from markupsafe import Markup, escape, soft_unicode
-except ImportError:
-    from ambari_jinja2._markupsafe import Markup, escape, soft_unicode
-
-
-# partials
-try:
-    from functools import partial
-except ImportError:
-    class partial(object):
-        def __init__(self, _func, *args, **kwargs):
-            self._func = _func
-            self._args = args
-            self._kwargs = kwargs
-        def __call__(self, *args, **kwargs):
-            kwargs.update(self._kwargs)
-            return self._func(*(self._args + args), **kwargs)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py
deleted file mode 100644
index 0561adf..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.visitor
-    ~~~~~~~~~~~~~~
-
-    This module implements a visitor for the nodes.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from ambari_jinja2.nodes import Node
-
-
-class NodeVisitor(object):
-    """Walks the abstract syntax tree and call visitor functions for every
-    node found.  The visitor functions may return values which will be
-    forwarded by the `visit` method.
-
-    Per default the visitor functions for the nodes are ``'visit_'`` +
-    class name of the node.  So a `TryFinally` node visit function would
-    be `visit_TryFinally`.  This behavior can be changed by overriding
-    the `get_visitor` function.  If no visitor function exists for a node
-    (return value `None`) the `generic_visit` visitor is used instead.
-    """
-
-    def get_visitor(self, node):
-        """Return the visitor function for this node or `None` if no visitor
-        exists for this node.  In that case the generic visit function is
-        used instead.
-        """
-        method = 'visit_' + node.__class__.__name__
-        return getattr(self, method, None)
-
-    def visit(self, node, *args, **kwargs):
-        """Visit a node."""
-        f = self.get_visitor(node)
-        if f is not None:
-            return f(node, *args, **kwargs)
-        return self.generic_visit(node, *args, **kwargs)
-
-    def generic_visit(self, node, *args, **kwargs):
-        """Called if no explicit visitor function exists for a node."""
-        for node in node.iter_child_nodes():
-            self.visit(node, *args, **kwargs)
-
-
-class NodeTransformer(NodeVisitor):
-    """Walks the abstract syntax tree and allows modifications of nodes.
-
-    The `NodeTransformer` will walk the AST and use the return value of the
-    visitor functions to replace or remove the old node.  If the return
-    value of the visitor function is `None` the node will be removed
-    from the previous location otherwise it's replaced with the return
-    value.  The return value may be the original node in which case no
-    replacement takes place.
-    """
-
-    def generic_visit(self, node, *args, **kwargs):
-        for field, old_value in node.iter_fields():
-            if isinstance(old_value, list):
-                new_values = []
-                for value in old_value:
-                    if isinstance(value, Node):
-                        value = self.visit(value, *args, **kwargs)
-                        if value is None:
-                            continue
-                        elif not isinstance(value, Node):
-                            new_values.extend(value)
-                            continue
-                    new_values.append(value)
-                old_value[:] = new_values
-            elif isinstance(old_value, Node):
-                new_node = self.visit(old_value, *args, **kwargs)
-                if new_node is None:
-                    delattr(node, field)
-                else:
-                    setattr(node, field, new_node)
-        return node
-
-    def visit_list(self, node, *args, **kwargs):
-        """As transformers may return lists in some places this method
-        can be used to enforce a list as return value.
-        """
-        rv = self.visit(node, *args, **kwargs)
-        if not isinstance(rv, list):
-            rv = [rv]
-        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg b/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg
deleted file mode 100644
index cc11c5c..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="300"
-   height="120"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   version="1.0"
-   sodipodi:docbase="/Users/mitsuhiko/Development/ambari_jinja2/artwork"
-   sodipodi:docname="jinjalogo.svg"
-   inkscape:export-filename="/Users/mitsuhiko/Development/ambari_jinja2/docs/_static/jinjabanner.png"
-   inkscape:export-xdpi="60"
-   inkscape:export-ydpi="60"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient6558">
-      <stop
-         style="stop-color:#575757;stop-opacity:1;"
-         offset="0"
-         id="stop6560" />
-      <stop
-         style="stop-color:#2f2f2f;stop-opacity:1;"
-         offset="1"
-         id="stop6562" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="radialGradient6564"
-       cx="61.297766"
-       cy="60.910986"
-       fx="61.297766"
-       fy="60.910986"
-       r="44.688254"
-       gradientTransform="matrix(1,0,0,0.945104,0,3.343747)"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="radialGradient6580"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,0.945104,0.355158,3.334402)"
-       cx="61.297766"
-       cy="60.910986"
-       fx="61.297766"
-       fy="60.910986"
-       r="44.688254" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="linearGradient4173"
-       x1="255.15521"
-       y1="32.347946"
-       x2="279.8912"
-       y2="32.347946"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.8073249,0,0,0.8073249,57.960878,7.4036303)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="linearGradient5145"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.7902775,0,0,0.82474,60.019977,8.0684132)"
-       x1="255.15521"
-       y1="32.347946"
-       x2="279.8912"
-       y2="32.347946" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     gridtolerance="10000"
-     guidetolerance="10"
-     objecttolerance="10"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="2.8"
-     inkscape:cx="137.4752"
-     inkscape:cy="57.574575"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     width="300px"
-     height="120px"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1396"
-     inkscape:window-height="900"
-     inkscape:window-x="0"
-     inkscape:window-y="22" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       style="font-size:12px;font-style:normal;font-weight:normal;fill:#f4f4f4;fill-opacity:1;stroke:#e7e7e7;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;font-family:Bitstream Vera Sans;stroke-miterlimit:4;stroke-dasharray:none"
-       d="M 165.36463,80.874808 L 165.36463,80.874808 L 153.32556,80.874808 L 153.32556,81.8344 L 147.64994,81.8344 L 147.64994,36.035583 L 165.36463,36.035583 L 165.36463,20.333129 C 170.58154,21.031083 173.07533,22.077914 172.84609,23.473621 C 172.78871,24.055258 172.21545,24.549594 171.12624,24.956624 L 171.12624,36.035583 L 189.09895,36.035583 L 189.09895,82.532286 L 183.33733,82.532286 L 183.33733,80.874808 L 171.12624,80.874808 L 171.12624,102.94548 L 165.36463,102.94548 L 165.36463,80.874808 M 153.32556,55.489173 L 153.32556,55.489173 L 165.36463,55.489173 L 165.36463,41.793146 L 153.32556,41.793146 L 153.32556,55.489173 M 171.12624,55.489173 L 171.12624,55.489173 L 183.33733,55.489173 L 183.33733,41.793146 L 171.12624,41.793146 L 171.12624,55.489173 M 183.33733,61.333977 L 183.33733,61.333977 L 171.12624,61.333977 L 171.12624,75.030006 L 183.33733,75.030006 L 183.33733,61.333977 M 165.36463,61.333977 L 165.36463,61.333977 L 153.32556,61.333977 L 153.32556,75.030006 L 165.364
 63,75.030006 L 165.36463,61.333977 M 132.85897,59.414792 C 137.33069,63.136883 140.99969,67.934848 143.86618,73.808701 L 139.13654,77.385372 C 137.24467,72.965445 134.6362,69.12707 131.31114,65.87024 L 131.31114,102.94548 L 125.63554,102.94548 L 125.63554,68.57455 C 122.31042,71.947693 118.52671,74.913707 114.28436,77.47261 L 109.64069,73.372526 C 121.50782,67.091566 130.62312,55.489212 136.98668,38.565417 L 116.26221,38.565417 L 116.26221,32.720615 L 125.80754,32.720615 L 125.80754,20.333129 C 130.85245,21.031083 133.31761,22.048838 133.20299,23.386383 C 133.14561,24.026183 132.57235,24.549594 131.48307,24.956624 L 131.48307,32.720615 L 140.77043,32.720615 L 143.60824,36.733469 C 140.68444,45.51526 137.10137,53.075692 132.85897,59.414792 M 254.11016,49.469901 L 254.11016,49.469901 L 254.11016,20.333129 C 259.21243,21.031083 261.67755,22.048838 261.50562,23.386383 C 261.44823,23.909869 261.04699,24.346044 260.30172,24.694917 C 260.30164,24.694986 260.30164,24.694986 260.30172,24.694
 917 L 260.30172,24.694917 L 259.78578,24.956624 L 259.78578,49.469901 L 277.15652,49.469901 L 277.15652,55.227471 L 259.78578,55.227471 L 259.78578,93.785712 L 281.45616,93.785712 L 281.45616,99.63051 L 232.35378,99.63051 L 232.35378,93.785712 L 254.11016,93.785712 L 254.11016,55.227471 L 236.22346,55.227471 L 236.22346,49.469901 L 254.11016,49.469901 M 225.5603,59.327554 C 231.12111,63.107798 235.62145,67.876693 239.06127,73.634235 L 234.76157,77.647079 C 231.60845,72.180322 227.82475,67.934848 223.41044,64.910648 L 223.41044,102.94548 L 217.73484,102.94548 L 217.73484,67.44049 C 212.91919,71.627831 207.70222,75.030021 202.084,77.647079 L 197.87027,73.198053 C 212.66118,66.917101 224.01239,55.372897 231.92377,38.565417 L 205.35172,38.565417 L 205.35172,32.720615 L 217.99283,32.720615 L 217.99283,20.333129 C 223.03774,21.031083 225.50291,22.048838 225.38829,23.386383 C 225.33089,24.026183 224.75765,24.549594 223.66837,24.956624 L 223.66837,32.720615 L 236.22346,32.720615 L 238.80326
 ,36.733469 C 235.13421,45.51526 230.71987,53.046611 225.5603,59.327554"
-       id="text4761" />
-    <path
-       style="font-size:44.09793472px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#b41717;fill-opacity:1;stroke:#7f2828;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Candara;stroke-miterlimit:4;stroke-dasharray:none"
-       d="M 149.14708,37.774469 C 148.97807,41.117899 148.84526,44.824225 148.74871,48.893456 C 148.67626,52.962754 148.3818,70.641328 148.38184,75.524422 C 148.3818,79.065795 148.05588,81.991266 147.40406,84.300835 C 146.75219,86.610422 145.72612,88.557071 144.32585,90.140779 C 142.94969,91.724494 141.17522,92.901283 139.00239,93.671139 C 136.82953,94.440996 134.22211,94.825935 131.18014,94.825935 C 128.83828,94.825935 126.73787,94.59498 124.87889,94.133049 L 125.4221,89.31593 C 127.13623,90.0418 128.92278,90.404734 130.78177,90.404733 C 132.85805,90.404734 134.66875,90.140782 136.2139,89.612876 C 137.78315,89.062981 139.02651,88.216133 139.94396,87.072335 C 140.8855,85.928548 141.54942,84.520804 141.93572,82.8491 C 142.34613,81.177412 142.55134,78.988811 142.55136,76.283285 C 142.55134,66.297119 142.62852,44.659257 142.26641,37.774469 L 149.14708,37.774469 M 166.38498,80.732697 L 159.83024,80.732697 C 160.16821,76.333498 160.33723,71.307412 160.33723,65.654424 C 160.33723,59.2976 
 159.91471,53.963567 159.06973,49.652319 L 166.31257,48.761483 C 166.02284,53.358679 165.87799,58.98965 165.87799,65.654424 C 165.87799,70.933479 166.04699,75.959565 166.38498,80.732697 M 167.90601,39.490159 C 167.90598,40.611994 167.5076,41.590815 166.7109,42.42662 C 165.91418,43.240515 164.79155,43.647442 163.343,43.647399 C 162.11172,43.647442 161.146,43.295504 160.44588,42.591595 C 159.76988,41.865769 159.43188,40.996927 159.43188,39.98507 C 159.43188,38.885304 159.84231,37.928485 160.66315,37.114591 C 161.48399,36.30078 162.61869,35.893853 164.06727,35.893811 C 165.25023,35.893853 166.17975,36.256783 166.85575,36.982609 C 167.55588,37.686526 167.90598,38.522373 167.90601,39.490159 M 206.72748,80.732697 L 200.13651,80.732697 C 200.66763,74.947749 200.93319,68.634899 200.9332,61.794122 C 200.93319,58.406756 200.1727,56.097177 198.65174,54.865371 C 197.15487,53.61163 195.00619,52.984747 192.20564,52.984714 C 188.77731,52.984747 185.61465,54.117535 182.71753,56.383099 C 182.71753,63
 .883761 182.76583,72.000287 182.86238,80.732697 L 176.27142,80.732697 C 176.68182,73.254058 176.88707,67.843042 176.88707,64.499632 C 176.88707,59.352589 176.3559,54.359493 175.29363,49.520339 L 181.66734,48.695493 L 182.35539,52.720761 L 182.64511,52.720761 C 186.21823,49.773323 190.04483,48.299592 194.12499,48.299567 C 198.13265,48.299592 201.23499,49.113454 203.43201,50.741118 C 205.62895,52.346863 206.72747,55.217334 206.72748,59.352563 C 206.72747,59.770507 206.70331,60.595362 206.65507,61.827118 C 206.60675,63.058915 206.5826,63.883761 206.58262,64.30167 C 206.5826,67.975018 206.63088,73.452022 206.72748,80.732697 M 222.69791,48.695493 C 222.28747,55.514282 222.08225,62.355041 222.08225,69.21778 C 222.08225,71.043461 222.14262,73.463019 222.26332,76.476468 C 222.40822,79.467925 222.4806,81.502559 222.48063,82.580363 C 222.4806,89.685068 219.51105,93.996287 213.57195,95.514024 L 211.76124,93.006484 C 213.90995,91.356766 215.2378,89.597085 215.74478,87.727431 C 216.49321,85.0439
 12 216.86743,79.324953 216.86743,70.570535 C 216.86743,61.178248 216.3846,54.16153 215.41887,49.520339 L 222.69791,48.695493 M 224.2551,39.490159 C 224.2551,40.611994 223.85673,41.590815 223.06006,42.42662 C 222.26332,43.240515 221.14069,43.647442 219.69213,43.647399 C 218.46084,43.647442 217.49515,43.295504 216.795,42.591595 C 216.119,41.865769 215.781,40.996927 215.781,39.98507 C 215.781,38.885304 216.19144,37.928485 217.01231,37.114591 C 217.83316,36.30078 218.96785,35.893853 220.4164,35.893811 C 221.5994,35.893853 222.52889,36.256783 223.20492,36.982609 C 223.90503,37.686526 224.2551,38.522373 224.2551,39.490159 M 259.60008,80.732697 L 253.91446,80.930661 C 253.62473,79.852857 253.47987,78.830045 253.4799,77.862216 L 253.11774,77.862216 C 250.14817,80.325772 246.10427,81.557546 240.98606,81.557547 C 238.20962,81.557546 235.8195,80.820682 233.81563,79.346948 C 231.81178,77.851221 230.80988,75.728607 230.80988,72.979099 C 230.80988,69.591724 232.37914,66.875216 235.51769,64.829574
  C 238.65625,62.761967 244.48667,61.67316 253.00913,61.563165 C 253.08155,61.035275 253.11772,60.430386 253.11774,59.748497 C 253.11772,57.043003 252.32104,55.239336 250.72765,54.337474 C 249.15832,53.435661 246.76819,52.984747 243.55721,52.984714 C 239.76681,52.984747 236.03678,53.413668 232.3671,54.271484 L 232.9827,49.718301 C 236.60411,48.77251 240.76873,48.299592 245.47658,48.299567 C 249.77395,48.299592 253.09359,49.113454 255.43545,50.741118 C 257.77728,52.346863 258.94819,55.096363 258.94824,58.989625 C 258.94819,60.023469 258.88785,61.904117 258.76715,64.631608 C 258.67054,67.337133 258.62228,69.140806 258.6223,70.042632 C 258.62228,74.045913 258.94819,77.609265 259.60008,80.732697 M 253.19019,74.331856 C 253.06945,70.988469 253.00909,67.986016 253.00913,65.324484 C 248.47027,65.324498 245.01786,65.632443 242.65187,66.248318 C 238.69248,67.348131 236.71278,69.448748 236.71278,72.550177 C 236.71278,75.541643 239.03044,77.037371 243.66588,77.037366 C 247.64942,77.037371 250.8
 2416,76.135534 253.19019,74.331856"
-       id="text3736"
-       sodipodi:nodetypes="ccsscssccscccsccccsccsccsscsssccccscscccsccccscsssccscscccscccsscsssccccccscsccscsccscscsccccssc" />
-    <path
-       style="fill:url(#radialGradient6564);fill-opacity:1.0;fill-rule:evenodd;stroke:#323232;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
-       d="M 105.45673,18.675923 C 105.45673,18.675923 88.211949,26.918461 74.172834,28.737898 C 60.133727,30.557333 33.360434,32.377571 28.045622,31.093256 C 22.730818,29.808941 18.915645,28.309196 18.915645,28.309196 L 20.021441,32.056583 L 16.609513,35.052471 L 17.2144,36.121726 L 18.61792,36.22764 L 22.92773,36.762252 L 23.532621,38.688909 L 25.937975,38.905784 L 27.143021,42.970927 C 27.143021,42.970927 32.254764,43.399628 33.758953,43.399628 C 35.263142,43.399628 38.271966,43.187802 38.271966,43.187802 L 38.371202,44.791657 L 39.477002,45.003495 L 39.477002,46.824227 L 37.066917,48.967759 L 37.671807,49.073671 L 37.671807,49.820127 C 37.671807,49.820127 32.255457,50.252157 30.049301,49.93109 C 27.843157,49.610006 27.440747,49.608286 27.440747,49.608286 L 27.242258,49.820127 L 27.143021,50.783455 L 27.643946,50.783455 L 27.84242,54.959544 L 38.976091,54.530844 L 38.172728,68.980747 L 38.073481,70.796442 L 28.645781,70.261816 L 28.546544,66.408513 L 30.649462,66.408513 L 30.85267
 3,64.910557 L 32.757107,64.481857 L 33.059555,64.058192 L 25.937975,62.343374 L 20.522364,63.947229 L 21.42496,64.698732 L 22.327572,64.698732 L 22.426809,65.984848 L 24.331254,66.09076 L 24.331254,69.838147 L 22.228335,70.372777 L 22.630009,71.225146 L 23.130934,71.547931 L 23.130934,74.437917 L 24.435218,74.437917 L 24.435218,87.813529 L 22.327572,88.13632 L 22.630009,91.989617 L 23.929569,92.206492 L 23.731093,100.98236 L 29.449141,101.08826 L 28.244105,92.418334 L 36.868446,92.206492 L 36.268285,96.912181 L 35.464925,100.23086 L 44.188501,100.33677 L 44.287739,91.777793 L 50.303506,91.243181 L 50.005786,96.700351 L 49.802585,99.90807 L 54.920484,99.90807 L 54.717274,91.132217 L 55.421397,91.243181 L 55.619882,87.067076 L 54.816521,87.067076 L 54.518798,85.352258 L 54.017874,80.429702 L 54.216359,74.760706 L 55.31743,74.760706 L 55.31743,71.336105 L 53.913913,71.442015 L 54.117112,67.402096 L 55.747469,67.240708 L 55.823083,65.929374 L 56.749319,65.793192 L 57.699176,65.071956 L 
 51.985842,63.896802 L 46.31977,65.15265 L 46.872668,66.060507 L 47.47283,66.010066 L 48.172228,65.984848 L 48.299828,67.639144 L 49.878196,67.563497 L 49.906548,71.144447 L 43.111042,70.988097 L 43.337879,67.160002 L 43.559978,63.679927 L 43.559978,59.105378 L 43.763188,54.288748 L 57.373101,53.592733 L 73.567955,52.659674 L 73.71917,55.736265 L 73.142647,63.120082 L 72.892183,69.9945 L 66.928387,69.888585 L 66.900039,65.071956 L 69.106918,64.991267 L 69.206169,63.629486 L 70.108765,63.493308 L 70.061506,63.226006 L 70.964116,63.175568 L 71.465028,62.504773 L 64.721507,60.926122 L 58.001612,62.368592 L 58.4789,63.200785 L 59.230285,63.1453 L 59.230285,63.523577 L 60.156518,63.523577 L 60.156518,65.046738 L 62.136575,65.071956 L 62.112937,69.298485 L 60.109259,69.298485 L 60.080907,70.261816 L 60.785031,70.342507 L 60.70942,74.009202 L 62.188552,74.089909 L 62.013701,88.620507 L 60.057282,89.018952 L 60.080907,89.714967 L 60.761406,89.714967 L 60.761406,93.437137 L 61.886113,93.43713
 7 L 61.588391,98.52109 L 61.210343,102.95945 L 68.331912,103.14605 L 68.105084,99.29275 L 67.580538,96.085028 L 67.476575,93.300955 L 73.520696,93.195041 L 73.345845,97.502272 L 73.317494,102.05159 L 76.729426,102.3189 L 81.3653,102.1323 L 82.820807,101.70358 L 82.017437,99.26753 L 81.818959,95.439438 L 81.440912,92.710853 L 87.206218,92.499027 L 86.955759,95.842931 L 86.932133,101.08826 L 89.238253,101.30009 L 91.520751,101.24965 L 92.621828,100.90165 L 91.969693,95.923633 L 91.747577,92.176239 L 92.725793,92.070324 L 92.749427,88.726422 L 93.02352,88.670945 L 92.976244,87.949712 L 91.846823,87.949712 L 91.619996,85.488427 L 91.520751,74.811143 L 92.371377,74.785924 L 92.371377,71.280616 L 92.725793,71.336105 L 92.725793,70.640088 L 91.468773,70.529127 L 91.497126,66.463987 L 93.600043,66.277382 L 93.477182,64.910557 L 94.403419,64.829863 L 94.351424,64.562549 L 95.580099,63.947229 L 89.337489,62.69138 L 82.995657,63.977495 L 83.39733,64.723951 L 84.375543,64.643256 L 84.427528,64.
 966046 L 85.254515,64.966046 L 85.301775,66.569901 L 87.357445,66.544681 L 87.532293,70.478688 L 80.264217,70.423216 L 79.413593,64.512124 L 78.733106,61.380041 L 78.184923,55.761484 L 78.510996,52.473053 L 92.999878,51.373557 L 93.047136,46.476221 L 93.774891,46.289613 L 93.727651,45.543159 L 93.174743,45.220372 C 93.174629,45.220372 85.252181,46.395266 82.745197,46.66284 C 82.0389,46.738209 82.09239,46.733258 81.516524,46.79397 L 81.440912,45.886118 L 78.444837,44.317564 L 78.482644,42.491786 L 79.512842,42.461518 L 79.588444,39.949808 C 79.588444,39.949808 85.728225,39.546834 88.009582,39.0117 C 90.290937,38.476559 93.524432,37.942456 93.524432,37.942456 L 95.055545,33.79662 L 98.089437,32.913987 L 98.339888,32.217972 L 105.20628,30.316548 L 105.98602,29.676006 L 103.37744,23.976741 L 103.62792,22.690624 L 104.95584,21.994611 L 105.91041,19.079404 L 105.45673,18.675923 z M 72.466874,40.403728 L 72.429067,42.476654 L 73.983813,42.542211 L 73.884576,44.509221 L 70.836515,46.506487 
 L 70.647496,47.081457 L 71.876167,47.091543 L 71.866712,47.575729 L 62.552432,48.029652 L 62.613863,46.652742 L 63.039175,45.966809 L 63.067524,45.528025 L 63.07698,44.579832 L 63.341609,43.949374 L 63.440849,43.439982 L 63.440849,43.076841 L 63.842533,41.47297 L 72.466874,40.403728 z M 52.987688,42.168984 L 52.760853,43.561027 L 53.488599,44.418431 L 53.441349,45.916386 L 54.117112,46.960408 L 53.942262,48.191039 L 54.443185,48.912273 L 44.939872,49.2855 L 44.916247,48.967759 L 46.017333,48.831579 L 46.069307,48.428097 L 43.66394,47.121797 L 43.536351,45.03375 L 44.689411,44.978276 L 44.788661,42.72883 L 52.987688,42.168984 z M 67.051262,74.276518 L 72.81657,74.649742 L 72.618099,82.411833 L 73.36947,88.776857 L 67.254465,88.565018 L 67.051262,74.276518 z M 28.44258,74.599304 L 37.671807,75.078442 L 36.868446,80.429702 L 36.868446,84.928593 L 37.520583,87.440302 L 28.494569,87.869006 L 28.44258,74.599304 z M 87.508658,74.649742 L 87.508658,87.924488 L 81.644113,88.353194 L 81.44091
 2,81.342592 L 80.788764,74.811143 L 87.508658,74.649742 z M 43.087416,74.947312 L 49.906548,74.972531 L 49.977434,87.278902 L 43.611966,87.389863 L 43.285891,83.400379 L 43.262266,79.441156 L 43.087416,74.947312 z "
-       id="path4735" />
-  </g>
-</svg>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py
deleted file mode 100644
index 96a81c1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from lib2to3 import fixer_base
-from lib2to3.fixer_util import Name, BlankLine
-
-
-class FixAltUnicode(fixer_base.BaseFix):
-    PATTERN = """
-    func=funcdef< 'def' name='__unicode__'
-                  parameters< '(' NAME ')' > any+ >
-    """
-
-    def transform(self, node, results):
-        name = results['name']
-        name.replace(Name('__str__', prefix=name.prefix))


[50/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py
new file mode 100644
index 0000000..83d1528
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2._stringdefs
+    ~~~~~~~~~~~~~~~~~~
+
+    Strings of all Unicode characters of a certain category.
+    Used for matching in Unicode-aware languages. Run to regenerate.
+
+    Inspired by chartypes_create.py from the MoinMoin project, original
+    implementation from Pygments.
+
+    :copyright: Copyright 2006-2009 by the Jinja team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
+
+Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb'
+
+Cn = u'\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0370\u0371\u0372\u0373\u0376\u0377\u0378\u0379\u037b\u037c\u037d\u037f\u0380\u0381\u0382\u0383\u038b\u038d\u03a2\u03cf\u0487\u04cf\u04fa\u04fb\u04fc\u04fd\u04fe\u04ff\u0510\u0511\u0512\u0513\u0514\u0515\u0516\u0517\u0518\u0519\u051a\u051b\u051c\u051d\u051e\u051f\u0520\u0521\u0522\u0523\u0524\u0525\u0526\u0527\u0528\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0557\u0558\u0560\u0588\u058b\u058c\u058d\u058e\u058f\u0590\u05ba\u05c8\u05c9\u05ca\u05cb\u05cc\u05cd\u05ce\u05cf\u05eb\u05ec\u05ed\u05ee\u05ef\u05f5\u05f6\u05f7\u05f8\u05f9\u05fa\u05fb\u05fc\u05fd\u05fe\u05ff\u0604\u0605\u0606\u0607\u0608\u0609\u060a\u0616\u0617\u0618\u0619\u061a\u061c\u061d\u0620\u063b\u063c\u063d\u063e\u063f\u065f\u070e\u074b\u074c\u076e\u076f\u0770\u0771\u0772\u0773\u0774\u0775\u0776\u0777\u0778\u0779\u077a\u077b\u077c\u077d\u077e\u077f\u07b2\u07b3\u07b4\u07b5\u07b6\u07b7\u07b8\u07b9\u07ba\u07bb\u07bc\u07bd\u07be
 \u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u07c7\u07c8\u07c9\u07ca\u07cb\u07cc\u07cd\u07ce\u07cf\u07d0\u07d1\u07d2\u07d3\u07d4\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07db\u07dc\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3\u07e4\u07e5\u07e6\u07e7\u07e8\u07e9\u07ea\u07eb\u07ec\u07ed\u07ee\u07ef\u07f0\u07f1\u07f2\u07f3\u07f4\u07f5\u07f6\u07f7\u07f8\u07f9\u07fa\u07fb\u07fc\u07fd\u07fe\u07ff\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u0817\u0818\u0819\u081a\u081b\u081c\u081d\u081e\u081f\u0820\u0821\u0822\u0823\u0824\u0825\u0826\u0827\u0828\u0829\u082a\u082b\u082c\u082d\u082e\u082f\u0830\u0831\u0832\u0833\u0834\u0835\u0836\u0837\u0838\u0839\u083a\u083b\u083c\u083d\u083e\u083f\u0840\u0841\u0842\u0843\u0844\u0845\u0846\u0847\u0848\u0849\u084a\u084b\u084c\u084d\u084e\u084f\u0850\u0851\u0852\u0853\u0854\u0855\u0856\u0857\u0858\u0859\u085a\u085b\u085c\u085d\u085e\u085f\u0860\u0861\u0862\u0863\u0864\
 u0865\u0866\u0867\u0868\u0869\u086a\u086b\u086c\u086d\u086e\u086f\u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087a\u087b\u087c\u087d\u087e\u087f\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0888\u0889\u088a\u088b\u088c\u088d\u088e\u088f\u0890\u0891\u0892\u0893\u0894\u0895\u0896\u0897\u0898\u0899\u089a\u089b\u089c\u089d\u089e\u089f\u08a0\u08a1\u08a2\u08a3\u08a4\u08a5\u08a6\u08a7\u08a8\u08a9\u08aa\u08ab\u08ac\u08ad\u08ae\u08af\u08b0\u08b1\u08b2\u08b3\u08b4\u08b5\u08b6\u08b7\u08b8\u08b9\u08ba\u08bb\u08bc\u08bd\u08be\u08bf\u08c0\u08c1\u08c2\u08c3\u08c4\u08c5\u08c6\u08c7\u08c8\u08c9\u08ca\u08cb\u08cc\u08cd\u08ce\u08cf\u08d0\u08d1\u08d2\u08d3\u08d4\u08d5\u08d6\u08d7\u08d8\u08d9\u08da\u08db\u08dc\u08dd\u08de\u08df\u08e0\u08e1\u08e2\u08e3\u08e4\u08e5\u08e6\u08e7\u08e8\u08e9\u08ea\u08eb\u08ec\u08ed\u08ee\u08ef\u08f0\u08f1\u08f2\u08f3\u08f4\u08f5\u08f6\u08f7\u08f8\u08f9\u08fa\u08fb\u08fc\u08fd\u08fe\u08ff\u0900\u093a\u093b\u094e\u094f\u0955\u0956\u0957\u0971\u0972\u0973\u
 0974\u0975\u0976\u0977\u0978\u0979\u097a\u097b\u097c\u097e\u097f\u0980\u0984\u098d\u098e\u0991\u0992\u09a9\u09b1\u09b3\u09b4\u09b5\u09ba\u09bb\u09c5\u09c6\u09c9\u09ca\u09cf\u09d0\u09d1\u09d2\u09d3\u09d4\u09d5\u09d6\u09d8\u09d9\u09da\u09db\u09de\u09e4\u09e5\u09fb\u09fc\u09fd\u09fe\u09ff\u0a00\u0a04\u0a0b\u0a0c\u0a0d\u0a0e\u0a11\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a\u0a3b\u0a3d\u0a43\u0a44\u0a45\u0a46\u0a49\u0a4a\u0a4e\u0a4f\u0a50\u0a51\u0a52\u0a53\u0a54\u0a55\u0a56\u0a57\u0a58\u0a5d\u0a5f\u0a60\u0a61\u0a62\u0a63\u0a64\u0a65\u0a75\u0a76\u0a77\u0a78\u0a79\u0a7a\u0a7b\u0a7c\u0a7d\u0a7e\u0a7f\u0a80\u0a84\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba\u0abb\u0ac6\u0aca\u0ace\u0acf\u0ad1\u0ad2\u0ad3\u0ad4\u0ad5\u0ad6\u0ad7\u0ad8\u0ad9\u0ada\u0adb\u0adc\u0add\u0ade\u0adf\u0ae4\u0ae5\u0af0\u0af2\u0af3\u0af4\u0af5\u0af6\u0af7\u0af8\u0af9\u0afa\u0afb\u0afc\u0afd\u0afe\u0aff\u0b00\u0b04\u0b0d\u0b0e\u0b11\u0b12\u0b29\u0b31\u0b34\u0b3a\u0b3b\u0b44\u0b45\u0b46\u0b49\u0b4a\u0b4e\u0b4f\u0b50\u0b51\u0b52\u0b53\u0
 b54\u0b55\u0b58\u0b59\u0b5a\u0b5b\u0b5e\u0b62\u0b63\u0b64\u0b65\u0b72\u0b73\u0b74\u0b75\u0b76\u0b77\u0b78\u0b79\u0b7a\u0b7b\u0b7c\u0b7d\u0b7e\u0b7f\u0b80\u0b81\u0b84\u0b8b\u0b8c\u0b8d\u0b91\u0b96\u0b97\u0b98\u0b9b\u0b9d\u0ba0\u0ba1\u0ba2\u0ba5\u0ba6\u0ba7\u0bab\u0bac\u0bad\u0bba\u0bbb\u0bbc\u0bbd\u0bc3\u0bc4\u0bc5\u0bc9\u0bce\u0bcf\u0bd0\u0bd1\u0bd2\u0bd3\u0bd4\u0bd5\u0bd6\u0bd8\u0bd9\u0bda\u0bdb\u0bdc\u0bdd\u0bde\u0bdf\u0be0\u0be1\u0be2\u0be3\u0be4\u0be5\u0bfb\u0bfc\u0bfd\u0bfe\u0bff\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a\u0c3b\u0c3c\u0c3d\u0c45\u0c49\u0c4e\u0c4f\u0c50\u0c51\u0c52\u0c53\u0c54\u0c57\u0c58\u0c59\u0c5a\u0c5b\u0c5c\u0c5d\u0c5e\u0c5f\u0c62\u0c63\u0c64\u0c65\u0c70\u0c71\u0c72\u0c73\u0c74\u0c75\u0c76\u0c77\u0c78\u0c79\u0c7a\u0c7b\u0c7c\u0c7d\u0c7e\u0c7f\u0c80\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba\u0cbb\u0cc5\u0cc9\u0cce\u0ccf\u0cd0\u0cd1\u0cd2\u0cd3\u0cd4\u0cd7\u0cd8\u0cd9\u0cda\u0cdb\u0cdc\u0cdd\u0cdf\u0ce2\u0ce3\u0ce4\u0ce5\u0cf0\u0cf1\u0cf2\u0cf3\u0cf4\u0cf5\u0c
 f6\u0cf7\u0cf8\u0cf9\u0cfa\u0cfb\u0cfc\u0cfd\u0cfe\u0cff\u0d00\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a\u0d3b\u0d3c\u0d3d\u0d44\u0d45\u0d49\u0d4e\u0d4f\u0d50\u0d51\u0d52\u0d53\u0d54\u0d55\u0d56\u0d58\u0d59\u0d5a\u0d5b\u0d5c\u0d5d\u0d5e\u0d5f\u0d62\u0d63\u0d64\u0d65\u0d70\u0d71\u0d72\u0d73\u0d74\u0d75\u0d76\u0d77\u0d78\u0d79\u0d7a\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f\u0d80\u0d81\u0d84\u0d97\u0d98\u0d99\u0db2\u0dbc\u0dbe\u0dbf\u0dc7\u0dc8\u0dc9\u0dcb\u0dcc\u0dcd\u0dce\u0dd5\u0dd7\u0de0\u0de1\u0de2\u0de3\u0de4\u0de5\u0de6\u0de7\u0de8\u0de9\u0dea\u0deb\u0dec\u0ded\u0dee\u0def\u0df0\u0df1\u0df5\u0df6\u0df7\u0df8\u0df9\u0dfa\u0dfb\u0dfc\u0dfd\u0dfe\u0dff\u0e00\u0e3b\u0e3c\u0e3d\u0e3e\u0e5c\u0e5d\u0e5e\u0e5f\u0e60\u0e61\u0e62\u0e63\u0e64\u0e65\u0e66\u0e67\u0e68\u0e69\u0e6a\u0e6b\u0e6c\u0e6d\u0e6e\u0e6f\u0e70\u0e71\u0e72\u0e73\u0e74\u0e75\u0e76\u0e77\u0e78\u0e79\u0e7a\u0e7b\u0e7c\u0e7d\u0e7e\u0e7f\u0e80\u0e83\u0e85\u0e86\u0e89\u0e8b\u0e8c\u0e8e\u0e8f\u0e90\u0e91\u0e92\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea
 8\u0ea9\u0eac\u0eba\u0ebe\u0ebf\u0ec5\u0ec7\u0ece\u0ecf\u0eda\u0edb\u0ede\u0edf\u0ee0\u0ee1\u0ee2\u0ee3\u0ee4\u0ee5\u0ee6\u0ee7\u0ee8\u0ee9\u0eea\u0eeb\u0eec\u0eed\u0eee\u0eef\u0ef0\u0ef1\u0ef2\u0ef3\u0ef4\u0ef5\u0ef6\u0ef7\u0ef8\u0ef9\u0efa\u0efb\u0efc\u0efd\u0efe\u0eff\u0f48\u0f6b\u0f6c\u0f6d\u0f6e\u0f6f\u0f70\u0f8c\u0f8d\u0f8e\u0f8f\u0f98\u0fbd\u0fcd\u0fce\u0fd2\u0fd3\u0fd4\u0fd5\u0fd6\u0fd7\u0fd8\u0fd9\u0fda\u0fdb\u0fdc\u0fdd\u0fde\u0fdf\u0fe0\u0fe1\u0fe2\u0fe3\u0fe4\u0fe5\u0fe6\u0fe7\u0fe8\u0fe9\u0fea\u0feb\u0fec\u0fed\u0fee\u0fef\u0ff0\u0ff1\u0ff2\u0ff3\u0ff4\u0ff5\u0ff6\u0ff7\u0ff8\u0ff9\u0ffa\u0ffb\u0ffc\u0ffd\u0ffe\u0fff\u1022\u1028\u102b\u1033\u1034\u1035\u103a\u103b\u103c\u103d\u103e\u103f\u105a\u105b\u105c\u105d\u105e\u105f\u1060\u1061\u1062\u1063\u1064\u1065\u1066\u1067\u1068\u1069\u106a\u106b\u106c\u106d\u106e\u106f\u1070\u1071\u1072\u1073\u1074\u1075\u1076\u1077\u1078\u1079\u107a\u107b\u107c\u107d\u107e\u107f\u1080\u1081\u1082\u1083\u1084\u1085\u1086\u1087\u1088\u1089
 \u108a\u108b\u108c\u108d\u108e\u108f\u1090\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\u109a\u109b\u109c\u109d\u109e\u109f\u10c6\u10c7\u10c8\u10c9\u10ca\u10cb\u10cc\u10cd\u10ce\u10cf\u10fd\u10fe\u10ff\u115a\u115b\u115c\u115d\u115e\u11a3\u11a4\u11a5\u11a6\u11a7\u11fa\u11fb\u11fc\u11fd\u11fe\u11ff\u1249\u124e\u124f\u1257\u1259\u125e\u125f\u1289\u128e\u128f\u12b1\u12b6\u12b7\u12bf\u12c1\u12c6\u12c7\u12d7\u1311\u1316\u1317\u135b\u135c\u135d\u135e\u137d\u137e\u137f\u139a\u139b\u139c\u139d\u139e\u139f\u13f5\u13f6\u13f7\u13f8\u13f9\u13fa\u13fb\u13fc\u13fd\u13fe\u13ff\u1400\u1677\u1678\u1679\u167a\u167b\u167c\u167d\u167e\u167f\u169d\u169e\u169f\u16f1\u16f2\u16f3\u16f4\u16f5\u16f6\u16f7\u16f8\u16f9\u16fa\u16fb\u16fc\u16fd\u16fe\u16ff\u170d\u1715\u1716\u1717\u1718\u1719\u171a\u171b\u171c\u171d\u171e\u171f\u1737\u1738\u1739\u173a\u173b\u173c\u173d\u173e\u173f\u1754\u1755\u1756\u1757\u1758\u1759\u175a\u175b\u175c\u175d\u175e\u175f\u176d\u1771\u1774\u1775\u1776\u1777\u1778\u1779\u177a\
 u177b\u177c\u177d\u177e\u177f\u17de\u17df\u17ea\u17eb\u17ec\u17ed\u17ee\u17ef\u17fa\u17fb\u17fc\u17fd\u17fe\u17ff\u180f\u181a\u181b\u181c\u181d\u181e\u181f\u1878\u1879\u187a\u187b\u187c\u187d\u187e\u187f\u18aa\u18ab\u18ac\u18ad\u18ae\u18af\u18b0\u18b1\u18b2\u18b3\u18b4\u18b5\u18b6\u18b7\u18b8\u18b9\u18ba\u18bb\u18bc\u18bd\u18be\u18bf\u18c0\u18c1\u18c2\u18c3\u18c4\u18c5\u18c6\u18c7\u18c8\u18c9\u18ca\u18cb\u18cc\u18cd\u18ce\u18cf\u18d0\u18d1\u18d2\u18d3\u18d4\u18d5\u18d6\u18d7\u18d8\u18d9\u18da\u18db\u18dc\u18dd\u18de\u18df\u18e0\u18e1\u18e2\u18e3\u18e4\u18e5\u18e6\u18e7\u18e8\u18e9\u18ea\u18eb\u18ec\u18ed\u18ee\u18ef\u18f0\u18f1\u18f2\u18f3\u18f4\u18f5\u18f6\u18f7\u18f8\u18f9\u18fa\u18fb\u18fc\u18fd\u18fe\u18ff\u191d\u191e\u191f\u192c\u192d\u192e\u192f\u193c\u193d\u193e\u193f\u1941\u1942\u1943\u196e\u196f\u1975\u1976\u1977\u1978\u1979\u197a\u197b\u197c\u197d\u197e\u197f\u19aa\u19ab\u19ac\u19ad\u19ae\u19af\u19ca\u19cb\u19cc\u19cd\u19ce\u19cf\u19da\u19db\u19dc\u19dd\u1a1c\u1a1d\u1a20\u
 1a21\u1a22\u1a23\u1a24\u1a25\u1a26\u1a27\u1a28\u1a29\u1a2a\u1a2b\u1a2c\u1a2d\u1a2e\u1a2f\u1a30\u1a31\u1a32\u1a33\u1a34\u1a35\u1a36\u1a37\u1a38\u1a39\u1a3a\u1a3b\u1a3c\u1a3d\u1a3e\u1a3f\u1a40\u1a41\u1a42\u1a43\u1a44\u1a45\u1a46\u1a47\u1a48\u1a49\u1a4a\u1a4b\u1a4c\u1a4d\u1a4e\u1a4f\u1a50\u1a51\u1a52\u1a53\u1a54\u1a55\u1a56\u1a57\u1a58\u1a59\u1a5a\u1a5b\u1a5c\u1a5d\u1a5e\u1a5f\u1a60\u1a61\u1a62\u1a63\u1a64\u1a65\u1a66\u1a67\u1a68\u1a69\u1a6a\u1a6b\u1a6c\u1a6d\u1a6e\u1a6f\u1a70\u1a71\u1a72\u1a73\u1a74\u1a75\u1a76\u1a77\u1a78\u1a79\u1a7a\u1a7b\u1a7c\u1a7d\u1a7e\u1a7f\u1a80\u1a81\u1a82\u1a83\u1a84\u1a85\u1a86\u1a87\u1a88\u1a89\u1a8a\u1a8b\u1a8c\u1a8d\u1a8e\u1a8f\u1a90\u1a91\u1a92\u1a93\u1a94\u1a95\u1a96\u1a97\u1a98\u1a99\u1a9a\u1a9b\u1a9c\u1a9d\u1a9e\u1a9f\u1aa0\u1aa1\u1aa2\u1aa3\u1aa4\u1aa5\u1aa6\u1aa7\u1aa8\u1aa9\u1aaa\u1aab\u1aac\u1aad\u1aae\u1aaf\u1ab0\u1ab1\u1ab2\u1ab3\u1ab4\u1ab5\u1ab6\u1ab7\u1ab8\u1ab9\u1aba\u1abb\u1abc\u1abd\u1abe\u1abf\u1ac0\u1ac1\u1ac2\u1ac3\u1ac4\u1ac5\u1ac6\u1
 ac7\u1ac8\u1ac9\u1aca\u1acb\u1acc\u1acd\u1ace\u1acf\u1ad0\u1ad1\u1ad2\u1ad3\u1ad4\u1ad5\u1ad6\u1ad7\u1ad8\u1ad9\u1ada\u1adb\u1adc\u1add\u1ade\u1adf\u1ae0\u1ae1\u1ae2\u1ae3\u1ae4\u1ae5\u1ae6\u1ae7\u1ae8\u1ae9\u1aea\u1aeb\u1aec\u1aed\u1aee\u1aef\u1af0\u1af1\u1af2\u1af3\u1af4\u1af5\u1af6\u1af7\u1af8\u1af9\u1afa\u1afb\u1afc\u1afd\u1afe\u1aff\u1b00\u1b01\u1b02\u1b03\u1b04\u1b05\u1b06\u1b07\u1b08\u1b09\u1b0a\u1b0b\u1b0c\u1b0d\u1b0e\u1b0f\u1b10\u1b11\u1b12\u1b13\u1b14\u1b15\u1b16\u1b17\u1b18\u1b19\u1b1a\u1b1b\u1b1c\u1b1d\u1b1e\u1b1f\u1b20\u1b21\u1b22\u1b23\u1b24\u1b25\u1b26\u1b27\u1b28\u1b29\u1b2a\u1b2b\u1b2c\u1b2d\u1b2e\u1b2f\u1b30\u1b31\u1b32\u1b33\u1b34\u1b35\u1b36\u1b37\u1b38\u1b39\u1b3a\u1b3b\u1b3c\u1b3d\u1b3e\u1b3f\u1b40\u1b41\u1b42\u1b43\u1b44\u1b45\u1b46\u1b47\u1b48\u1b49\u1b4a\u1b4b\u1b4c\u1b4d\u1b4e\u1b4f\u1b50\u1b51\u1b52\u1b53\u1b54\u1b55\u1b56\u1b57\u1b58\u1b59\u1b5a\u1b5b\u1b5c\u1b5d\u1b5e\u1b5f\u1b60\u1b61\u1b62\u1b63\u1b64\u1b65\u1b66\u1b67\u1b68\u1b69\u1b6a\u1b6b\u1b6c\u1b
 6d\u1b6e\u1b6f\u1b70\u1b71\u1b72\u1b73\u1b74\u1b75\u1b76\u1b77\u1b78\u1b79\u1b7a\u1b7b\u1b7c\u1b7d\u1b7e\u1b7f\u1b80\u1b81\u1b82\u1b83\u1b84\u1b85\u1b86\u1b87\u1b88\u1b89\u1b8a\u1b8b\u1b8c\u1b8d\u1b8e\u1b8f\u1b90\u1b91\u1b92\u1b93\u1b94\u1b95\u1b96\u1b97\u1b98\u1b99\u1b9a\u1b9b\u1b9c\u1b9d\u1b9e\u1b9f\u1ba0\u1ba1\u1ba2\u1ba3\u1ba4\u1ba5\u1ba6\u1ba7\u1ba8\u1ba9\u1baa\u1bab\u1bac\u1bad\u1bae\u1baf\u1bb0\u1bb1\u1bb2\u1bb3\u1bb4\u1bb5\u1bb6\u1bb7\u1bb8\u1bb9\u1bba\u1bbb\u1bbc\u1bbd\u1bbe\u1bbf\u1bc0\u1bc1\u1bc2\u1bc3\u1bc4\u1bc5\u1bc6\u1bc7\u1bc8\u1bc9\u1bca\u1bcb\u1bcc\u1bcd\u1bce\u1bcf\u1bd0\u1bd1\u1bd2\u1bd3\u1bd4\u1bd5\u1bd6\u1bd7\u1bd8\u1bd9\u1bda\u1bdb\u1bdc\u1bdd\u1bde\u1bdf\u1be0\u1be1\u1be2\u1be3\u1be4\u1be5\u1be6\u1be7\u1be8\u1be9\u1bea\u1beb\u1bec\u1bed\u1bee\u1bef\u1bf0\u1bf1\u1bf2\u1bf3\u1bf4\u1bf5\u1bf6\u1bf7\u1bf8\u1bf9\u1bfa\u1bfb\u1bfc\u1bfd\u1bfe\u1bff\u1c00\u1c01\u1c02\u1c03\u1c04\u1c05\u1c06\u1c07\u1c08\u1c09\u1c0a\u1c0b\u1c0c\u1c0d\u1c0e\u1c0f\u1c10\u1c11\u1c12\u1c1
 3\u1c14\u1c15\u1c16\u1c17\u1c18\u1c19\u1c1a\u1c1b\u1c1c\u1c1d\u1c1e\u1c1f\u1c20\u1c21\u1c22\u1c23\u1c24\u1c25\u1c26\u1c27\u1c28\u1c29\u1c2a\u1c2b\u1c2c\u1c2d\u1c2e\u1c2f\u1c30\u1c31\u1c32\u1c33\u1c34\u1c35\u1c36\u1c37\u1c38\u1c39\u1c3a\u1c3b\u1c3c\u1c3d\u1c3e\u1c3f\u1c40\u1c41\u1c42\u1c43\u1c44\u1c45\u1c46\u1c47\u1c48\u1c49\u1c4a\u1c4b\u1c4c\u1c4d\u1c4e\u1c4f\u1c50\u1c51\u1c52\u1c53\u1c54\u1c55\u1c56\u1c57\u1c58\u1c59\u1c5a\u1c5b\u1c5c\u1c5d\u1c5e\u1c5f\u1c60\u1c61\u1c62\u1c63\u1c64\u1c65\u1c66\u1c67\u1c68\u1c69\u1c6a\u1c6b\u1c6c\u1c6d\u1c6e\u1c6f\u1c70\u1c71\u1c72\u1c73\u1c74\u1c75\u1c76\u1c77\u1c78\u1c79\u1c7a\u1c7b\u1c7c\u1c7d\u1c7e\u1c7f\u1c80\u1c81\u1c82\u1c83\u1c84\u1c85\u1c86\u1c87\u1c88\u1c89\u1c8a\u1c8b\u1c8c\u1c8d\u1c8e\u1c8f\u1c90\u1c91\u1c92\u1c93\u1c94\u1c95\u1c96\u1c97\u1c98\u1c99\u1c9a\u1c9b\u1c9c\u1c9d\u1c9e\u1c9f\u1ca0\u1ca1\u1ca2\u1ca3\u1ca4\u1ca5\u1ca6\u1ca7\u1ca8\u1ca9\u1caa\u1cab\u1cac\u1cad\u1cae\u1caf\u1cb0\u1cb1\u1cb2\u1cb3\u1cb4\u1cb5\u1cb6\u1cb7\u1cb8\u1cb9
 \u1cba\u1cbb\u1cbc\u1cbd\u1cbe\u1cbf\u1cc0\u1cc1\u1cc2\u1cc3\u1cc4\u1cc5\u1cc6\u1cc7\u1cc8\u1cc9\u1cca\u1ccb\u1ccc\u1ccd\u1cce\u1ccf\u1cd0\u1cd1\u1cd2\u1cd3\u1cd4\u1cd5\u1cd6\u1cd7\u1cd8\u1cd9\u1cda\u1cdb\u1cdc\u1cdd\u1cde\u1cdf\u1ce0\u1ce1\u1ce2\u1ce3\u1ce4\u1ce5\u1ce6\u1ce7\u1ce8\u1ce9\u1cea\u1ceb\u1cec\u1ced\u1cee\u1cef\u1cf0\u1cf1\u1cf2\u1cf3\u1cf4\u1cf5\u1cf6\u1cf7\u1cf8\u1cf9\u1cfa\u1cfb\u1cfc\u1cfd\u1cfe\u1cff\u1dc4\u1dc5\u1dc6\u1dc7\u1dc8\u1dc9\u1dca\u1dcb\u1dcc\u1dcd\u1dce\u1dcf\u1dd0\u1dd1\u1dd2\u1dd3\u1dd4\u1dd5\u1dd6\u1dd7\u1dd8\u1dd9\u1dda\u1ddb\u1ddc\u1ddd\u1dde\u1ddf\u1de0\u1de1\u1de2\u1de3\u1de4\u1de5\u1de6\u1de7\u1de8\u1de9\u1dea\u1deb\u1dec\u1ded\u1dee\u1def\u1df0\u1df1\u1df2\u1df3\u1df4\u1df5\u1df6\u1df7\u1df8\u1df9\u1dfa\u1dfb\u1dfc\u1dfd\u1dfe\u1dff\u1e9c\u1e9d\u1e9e\u1e9f\u1efa\u1efb\u1efc\u1efd\u1efe\u1eff\u1f16\u1f17\u1f1e\u1f1f\u1f46\u1f47\u1f4e\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e\u1f7f\u1fb5\u1fc5\u1fd4\u1fd5\u1fdc\u1ff0\u1ff1\u1ff5\u1fff\u2064\u2065\u2066\
 u2067\u2068\u2069\u2072\u2073\u208f\u2095\u2096\u2097\u2098\u2099\u209a\u209b\u209c\u209d\u209e\u209f\u20b6\u20b7\u20b8\u20b9\u20ba\u20bb\u20bc\u20bd\u20be\u20bf\u20c0\u20c1\u20c2\u20c3\u20c4\u20c5\u20c6\u20c7\u20c8\u20c9\u20ca\u20cb\u20cc\u20cd\u20ce\u20cf\u20ec\u20ed\u20ee\u20ef\u20f0\u20f1\u20f2\u20f3\u20f4\u20f5\u20f6\u20f7\u20f8\u20f9\u20fa\u20fb\u20fc\u20fd\u20fe\u20ff\u214d\u214e\u214f\u2150\u2151\u2152\u2184\u2185\u2186\u2187\u2188\u2189\u218a\u218b\u218c\u218d\u218e\u218f\u23dc\u23dd\u23de\u23df\u23e0\u23e1\u23e2\u23e3\u23e4\u23e5\u23e6\u23e7\u23e8\u23e9\u23ea\u23eb\u23ec\u23ed\u23ee\u23ef\u23f0\u23f1\u23f2\u23f3\u23f4\u23f5\u23f6\u23f7\u23f8\u23f9\u23fa\u23fb\u23fc\u23fd\u23fe\u23ff\u2427\u2428\u2429\u242a\u242b\u242c\u242d\u242e\u242f\u2430\u2431\u2432\u2433\u2434\u2435\u2436\u2437\u2438\u2439\u243a\u243b\u243c\u243d\u243e\u243f\u244b\u244c\u244d\u244e\u244f\u2450\u2451\u2452\u2453\u2454\u2455\u2456\u2457\u2458\u2459\u245a\u245b\u245c\u245d\u245e\u245f\u269d\u269e\u269f\u
 26b2\u26b3\u26b4\u26b5\u26b6\u26b7\u26b8\u26b9\u26ba\u26bb\u26bc\u26bd\u26be\u26bf\u26c0\u26c1\u26c2\u26c3\u26c4\u26c5\u26c6\u26c7\u26c8\u26c9\u26ca\u26cb\u26cc\u26cd\u26ce\u26cf\u26d0\u26d1\u26d2\u26d3\u26d4\u26d5\u26d6\u26d7\u26d8\u26d9\u26da\u26db\u26dc\u26dd\u26de\u26df\u26e0\u26e1\u26e2\u26e3\u26e4\u26e5\u26e6\u26e7\u26e8\u26e9\u26ea\u26eb\u26ec\u26ed\u26ee\u26ef\u26f0\u26f1\u26f2\u26f3\u26f4\u26f5\u26f6\u26f7\u26f8\u26f9\u26fa\u26fb\u26fc\u26fd\u26fe\u26ff\u2700\u2705\u270a\u270b\u2728\u274c\u274e\u2753\u2754\u2755\u2757\u275f\u2760\u2795\u2796\u2797\u27b0\u27bf\u27c7\u27c8\u27c9\u27ca\u27cb\u27cc\u27cd\u27ce\u27cf\u27ec\u27ed\u27ee\u27ef\u2b14\u2b15\u2b16\u2b17\u2b18\u2b19\u2b1a\u2b1b\u2b1c\u2b1d\u2b1e\u2b1f\u2b20\u2b21\u2b22\u2b23\u2b24\u2b25\u2b26\u2b27\u2b28\u2b29\u2b2a\u2b2b\u2b2c\u2b2d\u2b2e\u2b2f\u2b30\u2b31\u2b32\u2b33\u2b34\u2b35\u2b36\u2b37\u2b38\u2b39\u2b3a\u2b3b\u2b3c\u2b3d\u2b3e\u2b3f\u2b40\u2b41\u2b42\u2b43\u2b44\u2b45\u2b46\u2b47\u2b48\u2b49\u2b4a\u2b4b\u2b4c\u2
 b4d\u2b4e\u2b4f\u2b50\u2b51\u2b52\u2b53\u2b54\u2b55\u2b56\u2b57\u2b58\u2b59\u2b5a\u2b5b\u2b5c\u2b5d\u2b5e\u2b5f\u2b60\u2b61\u2b62\u2b63\u2b64\u2b65\u2b66\u2b67\u2b68\u2b69\u2b6a\u2b6b\u2b6c\u2b6d\u2b6e\u2b6f\u2b70\u2b71\u2b72\u2b73\u2b74\u2b75\u2b76\u2b77\u2b78\u2b79\u2b7a\u2b7b\u2b7c\u2b7d\u2b7e\u2b7f\u2b80\u2b81\u2b82\u2b83\u2b84\u2b85\u2b86\u2b87\u2b88\u2b89\u2b8a\u2b8b\u2b8c\u2b8d\u2b8e\u2b8f\u2b90\u2b91\u2b92\u2b93\u2b94\u2b95\u2b96\u2b97\u2b98\u2b99\u2b9a\u2b9b\u2b9c\u2b9d\u2b9e\u2b9f\u2ba0\u2ba1\u2ba2\u2ba3\u2ba4\u2ba5\u2ba6\u2ba7\u2ba8\u2ba9\u2baa\u2bab\u2bac\u2bad\u2bae\u2baf\u2bb0\u2bb1\u2bb2\u2bb3\u2bb4\u2bb5\u2bb6\u2bb7\u2bb8\u2bb9\u2bba\u2bbb\u2bbc\u2bbd\u2bbe\u2bbf\u2bc0\u2bc1\u2bc2\u2bc3\u2bc4\u2bc5\u2bc6\u2bc7\u2bc8\u2bc9\u2bca\u2bcb\u2bcc\u2bcd\u2bce\u2bcf\u2bd0\u2bd1\u2bd2\u2bd3\u2bd4\u2bd5\u2bd6\u2bd7\u2bd8\u2bd9\u2bda\u2bdb\u2bdc\u2bdd\u2bde\u2bdf\u2be0\u2be1\u2be2\u2be3\u2be4\u2be5\u2be6\u2be7\u2be8\u2be9\u2bea\u2beb\u2bec\u2bed\u2bee\u2bef\u2bf0\u2bf1\u2bf2\u2b
 f3\u2bf4\u2bf5\u2bf6\u2bf7\u2bf8\u2bf9\u2bfa\u2bfb\u2bfc\u2bfd\u2bfe\u2bff\u2c2f\u2c5f\u2c60\u2c61\u2c62\u2c63\u2c64\u2c65\u2c66\u2c67\u2c68\u2c69\u2c6a\u2c6b\u2c6c\u2c6d\u2c6e\u2c6f\u2c70\u2c71\u2c72\u2c73\u2c74\u2c75\u2c76\u2c77\u2c78\u2c79\u2c7a\u2c7b\u2c7c\u2c7d\u2c7e\u2c7f\u2ceb\u2cec\u2ced\u2cee\u2cef\u2cf0\u2cf1\u2cf2\u2cf3\u2cf4\u2cf5\u2cf6\u2cf7\u2cf8\u2d26\u2d27\u2d28\u2d29\u2d2a\u2d2b\u2d2c\u2d2d\u2d2e\u2d2f\u2d66\u2d67\u2d68\u2d69\u2d6a\u2d6b\u2d6c\u2d6d\u2d6e\u2d70\u2d71\u2d72\u2d73\u2d74\u2d75\u2d76\u2d77\u2d78\u2d79\u2d7a\u2d7b\u2d7c\u2d7d\u2d7e\u2d7f\u2d97\u2d98\u2d99\u2d9a\u2d9b\u2d9c\u2d9d\u2d9e\u2d9f\u2da7\u2daf\u2db7\u2dbf\u2dc7\u2dcf\u2dd7\u2ddf\u2de0\u2de1\u2de2\u2de3\u2de4\u2de5\u2de6\u2de7\u2de8\u2de9\u2dea\u2deb\u2dec\u2ded\u2dee\u2def\u2df0\u2df1\u2df2\u2df3\u2df4\u2df5\u2df6\u2df7\u2df8\u2df9\u2dfa\u2dfb\u2dfc\u2dfd\u2dfe\u2dff\u2e18\u2e19\u2e1a\u2e1b\u2e1e\u2e1f\u2e20\u2e21\u2e22\u2e23\u2e24\u2e25\u2e26\u2e27\u2e28\u2e29\u2e2a\u2e2b\u2e2c\u2e2d\u2e2e\u2e2
 f\u2e30\u2e31\u2e32\u2e33\u2e34\u2e35\u2e36\u2e37\u2e38\u2e39\u2e3a\u2e3b\u2e3c\u2e3d\u2e3e\u2e3f\u2e40\u2e41\u2e42\u2e43\u2e44\u2e45\u2e46\u2e47\u2e48\u2e49\u2e4a\u2e4b\u2e4c\u2e4d\u2e4e\u2e4f\u2e50\u2e51\u2e52\u2e53\u2e54\u2e55\u2e56\u2e57\u2e58\u2e59\u2e5a\u2e5b\u2e5c\u2e5d\u2e5e\u2e5f\u2e60\u2e61\u2e62\u2e63\u2e64\u2e65\u2e66\u2e67\u2e68\u2e69\u2e6a\u2e6b\u2e6c\u2e6d\u2e6e\u2e6f\u2e70\u2e71\u2e72\u2e73\u2e74\u2e75\u2e76\u2e77\u2e78\u2e79\u2e7a\u2e7b\u2e7c\u2e7d\u2e7e\u2e7f\u2e9a\u2ef4\u2ef5\u2ef6\u2ef7\u2ef8\u2ef9\u2efa\u2efb\u2efc\u2efd\u2efe\u2eff\u2fd6\u2fd7\u2fd8\u2fd9\u2fda\u2fdb\u2fdc\u2fdd\u2fde\u2fdf\u2fe0\u2fe1\u2fe2\u2fe3\u2fe4\u2fe5\u2fe6\u2fe7\u2fe8\u2fe9\u2fea\u2feb\u2fec\u2fed\u2fee\u2fef\u2ffc\u2ffd\u2ffe\u2fff\u3040\u3097\u3098\u3100\u3101\u3102\u3103\u3104\u312d\u312e\u312f\u3130\u318f\u31b8\u31b9\u31ba\u31bb\u31bc\u31bd\u31be\u31bf\u31d0\u31d1\u31d2\u31d3\u31d4\u31d5\u31d6\u31d7\u31d8\u31d9\u31da\u31db\u31dc\u31dd\u31de\u31df\u31e0\u31e1\u31e2\u31e3\u31e4\u31e5
 \u31e6\u31e7\u31e8\u31e9\u31ea\u31eb\u31ec\u31ed\u31ee\u31ef\u321f\u3244\u3245\u3246\u3247\u3248\u3249\u324a\u324b\u324c\u324d\u324e\u324f\u32ff\u4db6\u4db7\u4db8\u4db9\u4dba\u4dbb\u4dbc\u4dbd\u4dbe\u4dbf\u9fbc\u9fbd\u9fbe\u9fbf\u9fc0\u9fc1\u9fc2\u9fc3\u9fc4\u9fc5\u9fc6\u9fc7\u9fc8\u9fc9\u9fca\u9fcb\u9fcc\u9fcd\u9fce\u9fcf\u9fd0\u9fd1\u9fd2\u9fd3\u9fd4\u9fd5\u9fd6\u9fd7\u9fd8\u9fd9\u9fda\u9fdb\u9fdc\u9fdd\u9fde\u9fdf\u9fe0\u9fe1\u9fe2\u9fe3\u9fe4\u9fe5\u9fe6\u9fe7\u9fe8\u9fe9\u9fea\u9feb\u9fec\u9fed\u9fee\u9fef\u9ff0\u9ff1\u9ff2\u9ff3\u9ff4\u9ff5\u9ff6\u9ff7\u9ff8\u9ff9\u9ffa\u9ffb\u9ffc\u9ffd\u9ffe\u9fff\ua48d\ua48e\ua48f\ua4c7\ua4c8\ua4c9\ua4ca\ua4cb\ua4cc\ua4cd\ua4ce\ua4cf\ua4d0\ua4d1\ua4d2\ua4d3\ua4d4\ua4d5\ua4d6\ua4d7\ua4d8\ua4d9\ua4da\ua4db\ua4dc\ua4dd\ua4de\ua4df\ua4e0\ua4e1\ua4e2\ua4e3\ua4e4\ua4e5\ua4e6\ua4e7\ua4e8\ua4e9\ua4ea\ua4eb\ua4ec\ua4ed\ua4ee\ua4ef\ua4f0\ua4f1\ua4f2\ua4f3\ua4f4\ua4f5\ua4f6\ua4f7\ua4f8\ua4f9\ua4fa\ua4fb\ua4fc\ua4fd\ua4fe\ua4ff\ua500\ua501\ua502\ua503\
 ua504\ua505\ua506\ua507\ua508\ua509\ua50a\ua50b\ua50c\ua50d\ua50e\ua50f\ua510\ua511\ua512\ua513\ua514\ua515\ua516\ua517\ua518\ua519\ua51a\ua51b\ua51c\ua51d\ua51e\ua51f\ua520\ua521\ua522\ua523\ua524\ua525\ua526\ua527\ua528\ua529\ua52a\ua52b\ua52c\ua52d\ua52e\ua52f\ua530\ua531\ua532\ua533\ua534\ua535\ua536\ua537\ua538\ua539\ua53a\ua53b\ua53c\ua53d\ua53e\ua53f\ua540\ua541\ua542\ua543\ua544\ua545\ua546\ua547\ua548\ua549\ua54a\ua54b\ua54c\ua54d\ua54e\ua54f\ua550\ua551\ua552\ua553\ua554\ua555\ua556\ua557\ua558\ua559\ua55a\ua55b\ua55c\ua55d\ua55e\ua55f\ua560\ua561\ua562\ua563\ua564\ua565\ua566\ua567\ua568\ua569\ua56a\ua56b\ua56c\ua56d\ua56e\ua56f\ua570\ua571\ua572\ua573\ua574\ua575\ua576\ua577\ua578\ua579\ua57a\ua57b\ua57c\ua57d\ua57e\ua57f\ua580\ua581\ua582\ua583\ua584\ua585\ua586\ua587\ua588\ua589\ua58a\ua58b\ua58c\ua58d\ua58e\ua58f\ua590\ua591\ua592\ua593\ua594\ua595\ua596\ua597\ua598\ua599\ua59a\ua59b\ua59c\ua59d\ua59e\ua59f\ua5a0\ua5a1\ua5a2\ua5a3\ua5a4\ua5a5\ua5a6\ua5a7\ua5a8\ua5a9\u
 a5aa\ua5ab\ua5ac\ua5ad\ua5ae\ua5af\ua5b0\ua5b1\ua5b2\ua5b3\ua5b4\ua5b5\ua5b6\ua5b7\ua5b8\ua5b9\ua5ba\ua5bb\ua5bc\ua5bd\ua5be\ua5bf\ua5c0\ua5c1\ua5c2\ua5c3\ua5c4\ua5c5\ua5c6\ua5c7\ua5c8\ua5c9\ua5ca\ua5cb\ua5cc\ua5cd\ua5ce\ua5cf\ua5d0\ua5d1\ua5d2\ua5d3\ua5d4\ua5d5\ua5d6\ua5d7\ua5d8\ua5d9\ua5da\ua5db\ua5dc\ua5dd\ua5de\ua5df\ua5e0\ua5e1\ua5e2\ua5e3\ua5e4\ua5e5\ua5e6\ua5e7\ua5e8\ua5e9\ua5ea\ua5eb\ua5ec\ua5ed\ua5ee\ua5ef\ua5f0\ua5f1\ua5f2\ua5f3\ua5f4\ua5f5\ua5f6\ua5f7\ua5f8\ua5f9\ua5fa\ua5fb\ua5fc\ua5fd\ua5fe\ua5ff\ua600\ua601\ua602\ua603\ua604\ua605\ua606\ua607\ua608\ua609\ua60a\ua60b\ua60c\ua60d\ua60e\ua60f\ua610\ua611\ua612\ua613\ua614\ua615\ua616\ua617\ua618\ua619\ua61a\ua61b\ua61c\ua61d\ua61e\ua61f\ua620\ua621\ua622\ua623\ua624\ua625\ua626\ua627\ua628\ua629\ua62a\ua62b\ua62c\ua62d\ua62e\ua62f\ua630\ua631\ua632\ua633\ua634\ua635\ua636\ua637\ua638\ua639\ua63a\ua63b\ua63c\ua63d\ua63e\ua63f\ua640\ua641\ua642\ua643\ua644\ua645\ua646\ua647\ua648\ua649\ua64a\ua64b\ua64c\ua64d\ua64e\ua64f\ua
 650\ua651\ua652\ua653\ua654\ua655\ua656\ua657\ua658\ua659\ua65a\ua65b\ua65c\ua65d\ua65e\ua65f\ua660\ua661\ua662\ua663\ua664\ua665\ua666\ua667\ua668\ua669\ua66a\ua66b\ua66c\ua66d\ua66e\ua66f\ua670\ua671\ua672\ua673\ua674\ua675\ua676\ua677\ua678\ua679\ua67a\ua67b\ua67c\ua67d\ua67e\ua67f\ua680\ua681\ua682\ua683\ua684\ua685\ua686\ua687\ua688\ua689\ua68a\ua68b\ua68c\ua68d\ua68e\ua68f\ua690\ua691\ua692\ua693\ua694\ua695\ua696\ua697\ua698\ua699\ua69a\ua69b\ua69c\ua69d\ua69e\ua69f\ua6a0\ua6a1\ua6a2\ua6a3\ua6a4\ua6a5\ua6a6\ua6a7\ua6a8\ua6a9\ua6aa\ua6ab\ua6ac\ua6ad\ua6ae\ua6af\ua6b0\ua6b1\ua6b2\ua6b3\ua6b4\ua6b5\ua6b6\ua6b7\ua6b8\ua6b9\ua6ba\ua6bb\ua6bc\ua6bd\ua6be\ua6bf\ua6c0\ua6c1\ua6c2\ua6c3\ua6c4\ua6c5\ua6c6\ua6c7\ua6c8\ua6c9\ua6ca\ua6cb\ua6cc\ua6cd\ua6ce\ua6cf\ua6d0\ua6d1\ua6d2\ua6d3\ua6d4\ua6d5\ua6d6\ua6d7\ua6d8\ua6d9\ua6da\ua6db\ua6dc\ua6dd\ua6de\ua6df\ua6e0\ua6e1\ua6e2\ua6e3\ua6e4\ua6e5\ua6e6\ua6e7\ua6e8\ua6e9\ua6ea\ua6eb\ua6ec\ua6ed\ua6ee\ua6ef\ua6f0\ua6f1\ua6f2\ua6f3\ua6f4\ua6f5\ua6
 f6\ua6f7\ua6f8\ua6f9\ua6fa\ua6fb\ua6fc\ua6fd\ua6fe\ua6ff\ua717\ua718\ua719\ua71a\ua71b\ua71c\ua71d\ua71e\ua71f\ua720\ua721\ua722\ua723\ua724\ua725\ua726\ua727\ua728\ua729\ua72a\ua72b\ua72c\ua72d\ua72e\ua72f\ua730\ua731\ua732\ua733\ua734\ua735\ua736\ua737\ua738\ua739\ua73a\ua73b\ua73c\ua73d\ua73e\ua73f\ua740\ua741\ua742\ua743\ua744\ua745\ua746\ua747\ua748\ua749\ua74a\ua74b\ua74c\ua74d\ua74e\ua74f\ua750\ua751\ua752\ua753\ua754\ua755\ua756\ua757\ua758\ua759\ua75a\ua75b\ua75c\ua75d\ua75e\ua75f\ua760\ua761\ua762\ua763\ua764\ua765\ua766\ua767\ua768\ua769\ua76a\ua76b\ua76c\ua76d\ua76e\ua76f\ua770\ua771\ua772\ua773\ua774\ua775\ua776\ua777\ua778\ua779\ua77a\ua77b\ua77c\ua77d\ua77e\ua77f\ua780\ua781\ua782\ua783\ua784\ua785\ua786\ua787\ua788\ua789\ua78a\ua78b\ua78c\ua78d\ua78e\ua78f\ua790\ua791\ua792\ua793\ua794\ua795\ua796\ua797\ua798\ua799\ua79a\ua79b\ua79c\ua79d\ua79e\ua79f\ua7a0\ua7a1\ua7a2\ua7a3\ua7a4\ua7a5\ua7a6\ua7a7\ua7a8\ua7a9\ua7aa\ua7ab\ua7ac\ua7ad\ua7ae\ua7af\ua7b0\ua7b1\ua7b2\ua7b
 3\ua7b4\ua7b5\ua7b6\ua7b7\ua7b8\ua7b9\ua7ba\ua7bb\ua7bc\ua7bd\ua7be\ua7bf\ua7c0\ua7c1\ua7c2\ua7c3\ua7c4\ua7c5\ua7c6\ua7c7\ua7c8\ua7c9\ua7ca\ua7cb\ua7cc\ua7cd\ua7ce\ua7cf\ua7d0\ua7d1\ua7d2\ua7d3\ua7d4\ua7d5\ua7d6\ua7d7\ua7d8\ua7d9\ua7da\ua7db\ua7dc\ua7dd\ua7de\ua7df\ua7e0\ua7e1\ua7e2\ua7e3\ua7e4\ua7e5\ua7e6\ua7e7\ua7e8\ua7e9\ua7ea\ua7eb\ua7ec\ua7ed\ua7ee\ua7ef\ua7f0\ua7f1\ua7f2\ua7f3\ua7f4\ua7f5\ua7f6\ua7f7\ua7f8\ua7f9\ua7fa\ua7fb\ua7fc\ua7fd\ua7fe\ua7ff\ua82c\ua82d\ua82e\ua82f\ua830\ua831\ua832\ua833\ua834\ua835\ua836\ua837\ua838\ua839\ua83a\ua83b\ua83c\ua83d\ua83e\ua83f\ua840\ua841\ua842\ua843\ua844\ua845\ua846\ua847\ua848\ua849\ua84a\ua84b\ua84c\ua84d\ua84e\ua84f\ua850\ua851\ua852\ua853\ua854\ua855\ua856\ua857\ua858\ua859\ua85a\ua85b\ua85c\ua85d\ua85e\ua85f\ua860\ua861\ua862\ua863\ua864\ua865\ua866\ua867\ua868\ua869\ua86a\ua86b\ua86c\ua86d\ua86e\ua86f\ua870\ua871\ua872\ua873\ua874\ua875\ua876\ua877\ua878\ua879\ua87a\ua87b\ua87c\ua87d\ua87e\ua87f\ua880\ua881\ua882\ua883\ua884\ua885
 \ua886\ua887\ua888\ua889\ua88a\ua88b\ua88c\ua88d\ua88e\ua88f\ua890\ua891\ua892\ua893\ua894\ua895\ua896\ua897\ua898\ua899\ua89a\ua89b\ua89c\ua89d\ua89e\ua89f\ua8a0\ua8a1\ua8a2\ua8a3\ua8a4\ua8a5\ua8a6\ua8a7\ua8a8\ua8a9\ua8aa\ua8ab\ua8ac\ua8ad\ua8ae\ua8af\ua8b0\ua8b1\ua8b2\ua8b3\ua8b4\ua8b5\ua8b6\ua8b7\ua8b8\ua8b9\ua8ba\ua8bb\ua8bc\ua8bd\ua8be\ua8bf\ua8c0\ua8c1\ua8c2\ua8c3\ua8c4\ua8c5\ua8c6\ua8c7\ua8c8\ua8c9\ua8ca\ua8cb\ua8cc\ua8cd\ua8ce\ua8cf\ua8d0\ua8d1\ua8d2\ua8d3\ua8d4\ua8d5\ua8d6\ua8d7\ua8d8\ua8d9\ua8da\ua8db\ua8dc\ua8dd\ua8de\ua8df\ua8e0\ua8e1\ua8e2\ua8e3\ua8e4\ua8e5\ua8e6\ua8e7\ua8e8\ua8e9\ua8ea\ua8eb\ua8ec\ua8ed\ua8ee\ua8ef\ua8f0\ua8f1\ua8f2\ua8f3\ua8f4\ua8f5\ua8f6\ua8f7\ua8f8\ua8f9\ua8fa\ua8fb\ua8fc\ua8fd\ua8fe\ua8ff\ua900\ua901\ua902\ua903\ua904\ua905\ua906\ua907\ua908\ua909\ua90a\ua90b\ua90c\ua90d\ua90e\ua90f\ua910\ua911\ua912\ua913\ua914\ua915\ua916\ua917\ua918\ua919\ua91a\ua91b\ua91c\ua91d\ua91e\ua91f\ua920\ua921\ua922\ua923\ua924\ua925\ua926\ua927\ua928\ua929\ua92a\ua92b\
 ua92c\ua92d\ua92e\ua92f\ua930\ua931\ua932\ua933\ua934\ua935\ua936\ua937\ua938\ua939\ua93a\ua93b\ua93c\ua93d\ua93e\ua93f\ua940\ua941\ua942\ua943\ua944\ua945\ua946\ua947\ua948\ua949\ua94a\ua94b\ua94c\ua94d\ua94e\ua94f\ua950\ua951\ua952\ua953\ua954\ua955\ua956\ua957\ua958\ua959\ua95a\ua95b\ua95c\ua95d\ua95e\ua95f\ua960\ua961\ua962\ua963\ua964\ua965\ua966\ua967\ua968\ua969\ua96a\ua96b\ua96c\ua96d\ua96e\ua96f\ua970\ua971\ua972\ua973\ua974\ua975\ua976\ua977\ua978\ua979\ua97a\ua97b\ua97c\ua97d\ua97e\ua97f\ua980\ua981\ua982\ua983\ua984\ua985\ua986\ua987\ua988\ua989\ua98a\ua98b\ua98c\ua98d\ua98e\ua98f\ua990\ua991\ua992\ua993\ua994\ua995\ua996\ua997\ua998\ua999\ua99a\ua99b\ua99c\ua99d\ua99e\ua99f\ua9a0\ua9a1\ua9a2\ua9a3\ua9a4\ua9a5\ua9a6\ua9a7\ua9a8\ua9a9\ua9aa\ua9ab\ua9ac\ua9ad\ua9ae\ua9af\ua9b0\ua9b1\ua9b2\ua9b3\ua9b4\ua9b5\ua9b6\ua9b7\ua9b8\ua9b9\ua9ba\ua9bb\ua9bc\ua9bd\ua9be\ua9bf\ua9c0\ua9c1\ua9c2\ua9c3\ua9c4\ua9c5\ua9c6\ua9c7\ua9c8\ua9c9\ua9ca\ua9cb\ua9cc\ua9cd\ua9ce\ua9cf\ua9d0\ua9d1\u
 a9d2\ua9d3\ua9d4\ua9d5\ua9d6\ua9d7\ua9d8\ua9d9\ua9da\ua9db\ua9dc\ua9dd\ua9de\ua9df\ua9e0\ua9e1\ua9e2\ua9e3\ua9e4\ua9e5\ua9e6\ua9e7\ua9e8\ua9e9\ua9ea\ua9eb\ua9ec\ua9ed\ua9ee\ua9ef\ua9f0\ua9f1\ua9f2\ua9f3\ua9f4\ua9f5\ua9f6\ua9f7\ua9f8\ua9f9\ua9fa\ua9fb\ua9fc\ua9fd\ua9fe\ua9ff\uaa00\uaa01\uaa02\uaa03\uaa04\uaa05\uaa06\uaa07\uaa08\uaa09\uaa0a\uaa0b\uaa0c\uaa0d\uaa0e\uaa0f\uaa10\uaa11\uaa12\uaa13\uaa14\uaa15\uaa16\uaa17\uaa18\uaa19\uaa1a\uaa1b\uaa1c\uaa1d\uaa1e\uaa1f\uaa20\uaa21\uaa22\uaa23\uaa24\uaa25\uaa26\uaa27\uaa28\uaa29\uaa2a\uaa2b\uaa2c\uaa2d\uaa2e\uaa2f\uaa30\uaa31\uaa32\uaa33\uaa34\uaa35\uaa36\uaa37\uaa38\uaa39\uaa3a\uaa3b\uaa3c\uaa3d\uaa3e\uaa3f\uaa40\uaa41\uaa42\uaa43\uaa44\uaa45\uaa46\uaa47\uaa48\uaa49\uaa4a\uaa4b\uaa4c\uaa4d\uaa4e\uaa4f\uaa50\uaa51\uaa52\uaa53\uaa54\uaa55\uaa56\uaa57\uaa58\uaa59\uaa5a\uaa5b\uaa5c\uaa5d\uaa5e\uaa5f\uaa60\uaa61\uaa62\uaa63\uaa64\uaa65\uaa66\uaa67\uaa68\uaa69\uaa6a\uaa6b\uaa6c\uaa6d\uaa6e\uaa6f\uaa70\uaa71\uaa72\uaa73\uaa74\uaa75\uaa76\uaa77\ua
 a78\uaa79\uaa7a\uaa7b\uaa7c\uaa7d\uaa7e\uaa7f\uaa80\uaa81\uaa82\uaa83\uaa84\uaa85\uaa86\uaa87\uaa88\uaa89\uaa8a\uaa8b\uaa8c\uaa8d\uaa8e\uaa8f\uaa90\uaa91\uaa92\uaa93\uaa94\uaa95\uaa96\uaa97\uaa98\uaa99\uaa9a\uaa9b\uaa9c\uaa9d\uaa9e\uaa9f\uaaa0\uaaa1\uaaa2\uaaa3\uaaa4\uaaa5\uaaa6\uaaa7\uaaa8\uaaa9\uaaaa\uaaab\uaaac\uaaad\uaaae\uaaaf\uaab0\uaab1\uaab2\uaab3\uaab4\uaab5\uaab6\uaab7\uaab8\uaab9\uaaba\uaabb\uaabc\uaabd\uaabe\uaabf\uaac0\uaac1\uaac2\uaac3\uaac4\uaac5\uaac6\uaac7\uaac8\uaac9\uaaca\uaacb\uaacc\uaacd\uaace\uaacf\uaad0\uaad1\uaad2\uaad3\uaad4\uaad5\uaad6\uaad7\uaad8\uaad9\uaada\uaadb\uaadc\uaadd\uaade\uaadf\uaae0\uaae1\uaae2\uaae3\uaae4\uaae5\uaae6\uaae7\uaae8\uaae9\uaaea\uaaeb\uaaec\uaaed\uaaee\uaaef\uaaf0\uaaf1\uaaf2\uaaf3\uaaf4\uaaf5\uaaf6\uaaf7\uaaf8\uaaf9\uaafa\uaafb\uaafc\uaafd\uaafe\uaaff\uab00\uab01\uab02\uab03\uab04\uab05\uab06\uab07\uab08\uab09\uab0a\uab0b\uab0c\uab0d\uab0e\uab0f\uab10\uab11\uab12\uab13\uab14\uab15\uab16\uab17\uab18\uab19\uab1a\uab1b\uab1c\uab1d\uab
 1e\uab1f\uab20\uab21\uab22\uab23\uab24\uab25\uab26\uab27\uab28\uab29\uab2a\uab2b\uab2c\uab2d\uab2e\uab2f\uab30\uab31\uab32\uab33\uab34\uab35\uab36\uab37\uab38\uab39\uab3a\uab3b\uab3c\uab3d\uab3e\uab3f\uab40\uab41\uab42\uab43\uab44\uab45\uab46\uab47\uab48\uab49\uab4a\uab4b\uab4c\uab4d\uab4e\uab4f\uab50\uab51\uab52\uab53\uab54\uab55\uab56\uab57\uab58\uab59\uab5a\uab5b\uab5c\uab5d\uab5e\uab5f\uab60\uab61\uab62\uab63\uab64\uab65\uab66\uab67\uab68\uab69\uab6a\uab6b\uab6c\uab6d\uab6e\uab6f\uab70\uab71\uab72\uab73\uab74\uab75\uab76\uab77\uab78\uab79\uab7a\uab7b\uab7c\uab7d\uab7e\uab7f\uab80\uab81\uab82\uab83\uab84\uab85\uab86\uab87\uab88\uab89\uab8a\uab8b\uab8c\uab8d\uab8e\uab8f\uab90\uab91\uab92\uab93\uab94\uab95\uab96\uab97\uab98\uab99\uab9a\uab9b\uab9c\uab9d\uab9e\uab9f\uaba0\uaba1\uaba2\uaba3\uaba4\uaba5\uaba6\uaba7\uaba8\uaba9\uabaa\uabab\uabac\uabad\uabae\uabaf\uabb0\uabb1\uabb2\uabb3\uabb4\uabb5\uabb6\uabb7\uabb8\uabb9\uabba\uabbb\uabbc\uabbd\uabbe\uabbf\uabc0\uabc1\uabc2\uabc3\uabc
 4\uabc5\uabc6\uabc7\uabc8\uabc9\uabca\uabcb\uabcc\uabcd\uabce\uabcf\uabd0\uabd1\uabd2\uabd3\uabd4\uabd5\uabd6\uabd7\uabd8\uabd9\uabda\uabdb\uabdc\uabdd\uabde\uabdf\uabe0\uabe1\uabe2\uabe3\uabe4\uabe5\uabe6\uabe7\uabe8\uabe9\uabea\uabeb\uabec\uabed\uabee\uabef\uabf0\uabf1\uabf2\uabf3\uabf4\uabf5\uabf6\uabf7\uabf8\uabf9\uabfa\uabfb\uabfc\uabfd\uabfe\uabff\ud7a4\ud7a5\ud7a6\ud7a7\ud7a8\ud7a9\ud7aa\ud7ab\ud7ac\ud7ad\ud7ae\ud7af\ud7b0\ud7b1\ud7b2\ud7b3\ud7b4\ud7b5\ud7b6\ud7b7\ud7b8\ud7b9\ud7ba\ud7bb\ud7bc\ud7bd\ud7be\ud7bf\ud7c0\ud7c1\ud7c2\ud7c3\ud7c4\ud7c5\ud7c6\ud7c7\ud7c8\ud7c9\ud7ca\ud7cb\ud7cc\ud7cd\ud7ce\ud7cf\ud7d0\ud7d1\ud7d2\ud7d3\ud7d4\ud7d5\ud7d6\ud7d7\ud7d8\ud7d9\ud7da\ud7db\ud7dc\ud7dd\ud7de\ud7df\ud7e0\ud7e1\ud7e2\ud7e3\ud7e4\ud7e5\ud7e6\ud7e7\ud7e8\ud7e9\ud7ea\ud7eb\ud7ec\ud7ed\ud7ee\ud7ef\ud7f0\ud7f1\ud7f2\ud7f3\ud7f4\ud7f5\ud7f6\ud7f7\ud7f8\ud7f9\ud7fa\ud7fb\ud7fc\ud7fd\ud7fe\ud7ff\ufa2e\ufa2f\ufa6b\ufa6c\ufa6d\ufa6e\ufa6f\ufada\ufadb\ufadc\ufadd\ufade\ufadf\ufae0\ufae1
 \ufae2\ufae3\ufae4\ufae5\ufae6\ufae7\ufae8\ufae9\ufaea\ufaeb\ufaec\ufaed\ufaee\ufaef\ufaf0\ufaf1\ufaf2\ufaf3\ufaf4\ufaf5\ufaf6\ufaf7\ufaf8\ufaf9\ufafa\ufafb\ufafc\ufafd\ufafe\ufaff\ufb07\ufb08\ufb09\ufb0a\ufb0b\ufb0c\ufb0d\ufb0e\ufb0f\ufb10\ufb11\ufb12\ufb18\ufb19\ufb1a\ufb1b\ufb1c\ufb37\ufb3d\ufb3f\ufb42\ufb45\ufbb2\ufbb3\ufbb4\ufbb5\ufbb6\ufbb7\ufbb8\ufbb9\ufbba\ufbbb\ufbbc\ufbbd\ufbbe\ufbbf\ufbc0\ufbc1\ufbc2\ufbc3\ufbc4\ufbc5\ufbc6\ufbc7\ufbc8\ufbc9\ufbca\ufbcb\ufbcc\ufbcd\ufbce\ufbcf\ufbd0\ufbd1\ufbd2\ufd40\ufd41\ufd42\ufd43\ufd44\ufd45\ufd46\ufd47\ufd48\ufd49\ufd4a\ufd4b\ufd4c\ufd4d\ufd4e\ufd4f\ufd90\ufd91\ufdc8\ufdc9\ufdca\ufdcb\ufdcc\ufdcd\ufdce\ufdcf\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea\ufdeb\ufdec\ufded\ufdee\ufdef\ufdfe\ufdff\ufe1a\ufe1b\ufe1c\ufe1d\ufe1e\ufe1f\ufe24\ufe25\ufe26\ufe27\ufe28\ufe29\ufe2a\ufe2b\ufe2c\ufe2d\ufe2e\ufe2f\ufe53\ufe67\ufe6c\
 ufe6d\ufe6e\ufe6f\ufe75\ufefd\ufefe\uff00\uffbf\uffc0\uffc1\uffc8\uffc9\uffd0\uffd1\uffd8\uffd9\uffdd\uffde\uffdf\uffe7\uffef\ufff0\ufff1\ufff2\ufff3\ufff4\ufff5\ufff6\ufff7\ufff8\ufffe'
+
+Co = u'\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009\ue00a\ue00b\ue00c\ue00d\ue00e\ue00f\ue010\ue011\ue012\ue013\ue014\ue015\ue016\ue017\ue018\ue019\ue01a\ue01b\ue01c\ue01d\ue01e\ue01f\ue020\ue021\ue022\ue023\ue024\ue025\ue026\ue027\ue028\ue029\ue02a\ue02b\ue02c\ue02d\ue02e\ue02f\ue030\ue031\ue032\ue033\ue034\ue035\ue036\ue037\ue038\ue039\ue03a\ue03b\ue03c\ue03d\ue03e\ue03f\ue040\ue041\ue042\ue043\ue044\ue045\ue046\ue047\ue048\ue049\ue04a\ue04b\ue04c\ue04d\ue04e\ue04f\ue050\ue051\ue052\ue053\ue054\ue055\ue056\ue057\ue058\ue059\ue05a\ue05b\ue05c\ue05d\ue05e\ue05f\ue060\ue061\ue062\ue063\ue064\ue065\ue066\ue067\ue068\ue069\ue06a\ue06b\ue06c\ue06d\ue06e\ue06f\ue070\ue071\ue072\ue073\ue074\ue075\ue076\ue077\ue078\ue079\ue07a\ue07b\ue07c\ue07d\ue07e\ue07f\ue080\ue081\ue082\ue083\ue084\ue085\ue086\ue087\ue088\ue089\ue08a\ue08b\ue08c\ue08d\ue08e\ue08f\ue090\ue091\ue092\ue093\ue094\ue095\ue096\ue097\ue098\ue099\ue09a\ue09b\ue09c\ue09d\ue09e\ue09f\ue0a0\ue0a1\ue0a2\ue0a3\ue0a4
 \ue0a5\ue0a6\ue0a7\ue0a8\ue0a9\ue0aa\ue0ab\ue0ac\ue0ad\ue0ae\ue0af\ue0b0\ue0b1\ue0b2\ue0b3\ue0b4\ue0b5\ue0b6\ue0b7\ue0b8\ue0b9\ue0ba\ue0bb\ue0bc\ue0bd\ue0be\ue0bf\ue0c0\ue0c1\ue0c2\ue0c3\ue0c4\ue0c5\ue0c6\ue0c7\ue0c8\ue0c9\ue0ca\ue0cb\ue0cc\ue0cd\ue0ce\ue0cf\ue0d0\ue0d1\ue0d2\ue0d3\ue0d4\ue0d5\ue0d6\ue0d7\ue0d8\ue0d9\ue0da\ue0db\ue0dc\ue0dd\ue0de\ue0df\ue0e0\ue0e1\ue0e2\ue0e3\ue0e4\ue0e5\ue0e6\ue0e7\ue0e8\ue0e9\ue0ea\ue0eb\ue0ec\ue0ed\ue0ee\ue0ef\ue0f0\ue0f1\ue0f2\ue0f3\ue0f4\ue0f5\ue0f6\ue0f7\ue0f8\ue0f9\ue0fa\ue0fb\ue0fc\ue0fd\ue0fe\ue0ff\ue100\ue101\ue102\ue103\ue104\ue105\ue106\ue107\ue108\ue109\ue10a\ue10b\ue10c\ue10d\ue10e\ue10f\ue110\ue111\ue112\ue113\ue114\ue115\ue116\ue117\ue118\ue119\ue11a\ue11b\ue11c\ue11d\ue11e\ue11f\ue120\ue121\ue122\ue123\ue124\ue125\ue126\ue127\ue128\ue129\ue12a\ue12b\ue12c\ue12d\ue12e\ue12f\ue130\ue131\ue132\ue133\ue134\ue135\ue136\ue137\ue138\ue139\ue13a\ue13b\ue13c\ue13d\ue13e\ue13f\ue140\ue141\ue142\ue143\ue144\ue145\ue146\ue147\ue148\ue149\ue14a\
 ue14b\ue14c\ue14d\ue14e\ue14f\ue150\ue151\ue152\ue153\ue154\ue155\ue156\ue157\ue158\ue159\ue15a\ue15b\ue15c\ue15d\ue15e\ue15f\ue160\ue161\ue162\ue163\ue164\ue165\ue166\ue167\ue168\ue169\ue16a\ue16b\ue16c\ue16d\ue16e\ue16f\ue170\ue171\ue172\ue173\ue174\ue175\ue176\ue177\ue178\ue179\ue17a\ue17b\ue17c\ue17d\ue17e\ue17f\ue180\ue181\ue182\ue183\ue184\ue185\ue186\ue187\ue188\ue189\ue18a\ue18b\ue18c\ue18d\ue18e\ue18f\ue190\ue191\ue192\ue193\ue194\ue195\ue196\ue197\ue198\ue199\ue19a\ue19b\ue19c\ue19d\ue19e\ue19f\ue1a0\ue1a1\ue1a2\ue1a3\ue1a4\ue1a5\ue1a6\ue1a7\ue1a8\ue1a9\ue1aa\ue1ab\ue1ac\ue1ad\ue1ae\ue1af\ue1b0\ue1b1\ue1b2\ue1b3\ue1b4\ue1b5\ue1b6\ue1b7\ue1b8\ue1b9\ue1ba\ue1bb\ue1bc\ue1bd\ue1be\ue1bf\ue1c0\ue1c1\ue1c2\ue1c3\ue1c4\ue1c5\ue1c6\ue1c7\ue1c8\ue1c9\ue1ca\ue1cb\ue1cc\ue1cd\ue1ce\ue1cf\ue1d0\ue1d1\ue1d2\ue1d3\ue1d4\ue1d5\ue1d6\ue1d7\ue1d8\ue1d9\ue1da\ue1db\ue1dc\ue1dd\ue1de\ue1df\ue1e0\ue1e1\ue1e2\ue1e3\ue1e4\ue1e5\ue1e6\ue1e7\ue1e8\ue1e9\ue1ea\ue1eb\ue1ec\ue1ed\ue1ee\ue1ef\ue1f0\u
 e1f1\ue1f2\ue1f3\ue1f4\ue1f5\ue1f6\ue1f7\ue1f8\ue1f9\ue1fa\ue1fb\ue1fc\ue1fd\ue1fe\ue1ff\ue200\ue201\ue202\ue203\ue204\ue205\ue206\ue207\ue208\ue209\ue20a\ue20b\ue20c\ue20d\ue20e\ue20f\ue210\ue211\ue212\ue213\ue214\ue215\ue216\ue217\ue218\ue219\ue21a\ue21b\ue21c\ue21d\ue21e\ue21f\ue220\ue221\ue222\ue223\ue224\ue225\ue226\ue227\ue228\ue229\ue22a\ue22b\ue22c\ue22d\ue22e\ue22f\ue230\ue231\ue232\ue233\ue234\ue235\ue236\ue237\ue238\ue239\ue23a\ue23b\ue23c\ue23d\ue23e\ue23f\ue240\ue241\ue242\ue243\ue244\ue245\ue246\ue247\ue248\ue249\ue24a\ue24b\ue24c\ue24d\ue24e\ue24f\ue250\ue251\ue252\ue253\ue254\ue255\ue256\ue257\ue258\ue259\ue25a\ue25b\ue25c\ue25d\ue25e\ue25f\ue260\ue261\ue262\ue263\ue264\ue265\ue266\ue267\ue268\ue269\ue26a\ue26b\ue26c\ue26d\ue26e\ue26f\ue270\ue271\ue272\ue273\ue274\ue275\ue276\ue277\ue278\ue279\ue27a\ue27b\ue27c\ue27d\ue27e\ue27f\ue280\ue281\ue282\ue283\ue284\ue285\ue286\ue287\ue288\ue289\ue28a\ue28b\ue28c\ue28d\ue28e\ue28f\ue290\ue291\ue292\ue293\ue294\ue295\ue296\ue
 297\ue298\ue299\ue29a\ue29b\ue29c\ue29d\ue29e\ue29f\ue2a0\ue2a1\ue2a2\ue2a3\ue2a4\ue2a5\ue2a6\ue2a7\ue2a8\ue2a9\ue2aa\ue2ab\ue2ac\ue2ad\ue2ae\ue2af\ue2b0\ue2b1\ue2b2\ue2b3\ue2b4\ue2b5\ue2b6\ue2b7\ue2b8\ue2b9\ue2ba\ue2bb\ue2bc\ue2bd\ue2be\ue2bf\ue2c0\ue2c1\ue2c2\ue2c3\ue2c4\ue2c5\ue2c6\ue2c7\ue2c8\ue2c9\ue2ca\ue2cb\ue2cc\ue2cd\ue2ce\ue2cf\ue2d0\ue2d1\ue2d2\ue2d3\ue2d4\ue2d5\ue2d6\ue2d7\ue2d8\ue2d9\ue2da\ue2db\ue2dc\ue2dd\ue2de\ue2df\ue2e0\ue2e1\ue2e2\ue2e3\ue2e4\ue2e5\ue2e6\ue2e7\ue2e8\ue2e9\ue2ea\ue2eb\ue2ec\ue2ed\ue2ee\ue2ef\ue2f0\ue2f1\ue2f2\ue2f3\ue2f4\ue2f5\ue2f6\ue2f7\ue2f8\ue2f9\ue2fa\ue2fb\ue2fc\ue2fd\ue2fe\ue2ff\ue300\ue301\ue302\ue303\ue304\ue305\ue306\ue307\ue308\ue309\ue30a\ue30b\ue30c\ue30d\ue30e\ue30f\ue310\ue311\ue312\ue313\ue314\ue315\ue316\ue317\ue318\ue319\ue31a\ue31b\ue31c\ue31d\ue31e\ue31f\ue320\ue321\ue322\ue323\ue324\ue325\ue326\ue327\ue328\ue329\ue32a\ue32b\ue32c\ue32d\ue32e\ue32f\ue330\ue331\ue332\ue333\ue334\ue335\ue336\ue337\ue338\ue339\ue33a\ue33b\ue33c\ue3
 3d\ue33e\ue33f\ue340\ue341\ue342\ue343\ue344\ue345\ue346\ue347\ue348\ue349\ue34a\ue34b\ue34c\ue34d\ue34e\ue34f\ue350\ue351\ue352\ue353\ue354\ue355\ue356\ue357\ue358\ue359\ue35a\ue35b\ue35c\ue35d\ue35e\ue35f\ue360\ue361\ue362\ue363\ue364\ue365\ue366\ue367\ue368\ue369\ue36a\ue36b\ue36c\ue36d\ue36e\ue36f\ue370\ue371\ue372\ue373\ue374\ue375\ue376\ue377\ue378\ue379\ue37a\ue37b\ue37c\ue37d\ue37e\ue37f\ue380\ue381\ue382\ue383\ue384\ue385\ue386\ue387\ue388\ue389\ue38a\ue38b\ue38c\ue38d\ue38e\ue38f\ue390\ue391\ue392\ue393\ue394\ue395\ue396\ue397\ue398\ue399\ue39a\ue39b\ue39c\ue39d\ue39e\ue39f\ue3a0\ue3a1\ue3a2\ue3a3\ue3a4\ue3a5\ue3a6\ue3a7\ue3a8\ue3a9\ue3aa\ue3ab\ue3ac\ue3ad\ue3ae\ue3af\ue3b0\ue3b1\ue3b2\ue3b3\ue3b4\ue3b5\ue3b6\ue3b7\ue3b8\ue3b9\ue3ba\ue3bb\ue3bc\ue3bd\ue3be\ue3bf\ue3c0\ue3c1\ue3c2\ue3c3\ue3c4\ue3c5\ue3c6\ue3c7\ue3c8\ue3c9\ue3ca\ue3cb\ue3cc\ue3cd\ue3ce\ue3cf\ue3d0\ue3d1\ue3d2\ue3d3\ue3d4\ue3d5\ue3d6\ue3d7\ue3d8\ue3d9\ue3da\ue3db\ue3dc\ue3dd\ue3de\ue3df\ue3e0\ue3e1\ue3e2\ue3e
 3\ue3e4\ue3e5\ue3e6\ue3e7\ue3e8\ue3e9\ue3ea\ue3eb\ue3ec\ue3ed\ue3ee\ue3ef\ue3f0\ue3f1\ue3f2\ue3f3\ue3f4\ue3f5\ue3f6\ue3f7\ue3f8\ue3f9\ue3fa\ue3fb\ue3fc\ue3fd\ue3fe\ue3ff\ue400\ue401\ue402\ue403\ue404\ue405\ue406\ue407\ue408\ue409\ue40a\ue40b\ue40c\ue40d\ue40e\ue40f\ue410\ue411\ue412\ue413\ue414\ue415\ue416\ue417\ue418\ue419\ue41a\ue41b\ue41c\ue41d\ue41e\ue41f\ue420\ue421\ue422\ue423\ue424\ue425\ue426\ue427\ue428\ue429\ue42a\ue42b\ue42c\ue42d\ue42e\ue42f\ue430\ue431\ue432\ue433\ue434\ue435\ue436\ue437\ue438\ue439\ue43a\ue43b\ue43c\ue43d\ue43e\ue43f\ue440\ue441\ue442\ue443\ue444\ue445\ue446\ue447\ue448\ue449\ue44a\ue44b\ue44c\ue44d\ue44e\ue44f\ue450\ue451\ue452\ue453\ue454\ue455\ue456\ue457\ue458\ue459\ue45a\ue45b\ue45c\ue45d\ue45e\ue45f\ue460\ue461\ue462\ue463\ue464\ue465\ue466\ue467\ue468\ue469\ue46a\ue46b\ue46c\ue46d\ue46e\ue46f\ue470\ue471\ue472\ue473\ue474\ue475\ue476\ue477\ue478\ue479\ue47a\ue47b\ue47c\ue47d\ue47e\ue47f\ue480\ue481\ue482\ue483\ue484\ue485\ue486\ue487\ue488\ue489
 \ue48a\ue48b\ue48c\ue48d\ue48e\ue48f\ue490\ue491\ue492\ue493\ue494\ue495\ue496\ue497\ue498\ue499\ue49a\ue49b\ue49c\ue49d\ue49e\ue49f\ue4a0\ue4a1\ue4a2\ue4a3\ue4a4\ue4a5\ue4a6\ue4a7\ue4a8\ue4a9\ue4aa\ue4ab\ue4ac\ue4ad\ue4ae\ue4af\ue4b0\ue4b1\ue4b2\ue4b3\ue4b4\ue4b5\ue4b6\ue4b7\ue4b8\ue4b9\ue4ba\ue4bb\ue4bc\ue4bd\ue4be\ue4bf\ue4c0\ue4c1\ue4c2\ue4c3\ue4c4\ue4c5\ue4c6\ue4c7\ue4c8\ue4c9\ue4ca\ue4cb\ue4cc\ue4cd\ue4ce\ue4cf\ue4d0\ue4d1\ue4d2\ue4d3\ue4d4\ue4d5\ue4d6\ue4d7\ue4d8\ue4d9\ue4da\ue4db\ue4dc\ue4dd\ue4de\ue4df\ue4e0\ue4e1\ue4e2\ue4e3\ue4e4\ue4e5\ue4e6\ue4e7\ue4e8\ue4e9\ue4ea\ue4eb\ue4ec\ue4ed\ue4ee\ue4ef\ue4f0\ue4f1\ue4f2\ue4f3\ue4f4\ue4f5\ue4f6\ue4f7\ue4f8\ue4f9\ue4fa\ue4fb\ue4fc\ue4fd\ue4fe\ue4ff\ue500\ue501\ue502\ue503\ue504\ue505\ue506\ue507\ue508\ue509\ue50a\ue50b\ue50c\ue50d\ue50e\ue50f\ue510\ue511\ue512\ue513\ue514\ue515\ue516\ue517\ue518\ue519\ue51a\ue51b\ue51c\ue51d\ue51e\ue51f\ue520\ue521\ue522\ue523\ue524\ue525\ue526\ue527\ue528\ue529\ue52a\ue52b\ue52c\ue52d\ue52e\ue52f\
 ue530\ue531\ue532\ue533\ue534\ue535\ue536\ue537\ue538\ue539\ue53a\ue53b\ue53c\ue53d\ue53e\ue53f\ue540\ue541\ue542\ue543\ue544\ue545\ue546\ue547\ue548\ue549\ue54a\ue54b\ue54c\ue54d\ue54e\ue54f\ue550\ue551\ue552\ue553\ue554\ue555\ue556\ue557\ue558\ue559\ue55a\ue55b\ue55c\ue55d\ue55e\ue55f\ue560\ue561\ue562\ue563\ue564\ue565\ue566\ue567\ue568\ue569\ue56a\ue56b\ue56c\ue56d\ue56e\ue56f\ue570\ue571\ue572\ue573\ue574\ue575\ue576\ue577\ue578\ue579\ue57a\ue57b\ue57c\ue57d\ue57e\ue57f\ue580\ue581\ue582\ue583\ue584\ue585\ue586\ue587\ue588\ue589\ue58a\ue58b\ue58c\ue58d\ue58e\ue58f\ue590\ue591\ue592\ue593\ue594\ue595\ue596\ue597\ue598\ue599\ue59a\ue59b\ue59c\ue59d\ue59e\ue59f\ue5a0\ue5a1\ue5a2\ue5a3\ue5a4\ue5a5\ue5a6\ue5a7\ue5a8\ue5a9\ue5aa\ue5ab\ue5ac\ue5ad\ue5ae\ue5af\ue5b0\ue5b1\ue5b2\ue5b3\ue5b4\ue5b5\ue5b6\ue5b7\ue5b8\ue5b9\ue5ba\ue5bb\ue5bc\ue5bd\ue5be\ue5bf\ue5c0\ue5c1\ue5c2\ue5c3\ue5c4\ue5c5\ue5c6\ue5c7\ue5c8\ue5c9\ue5ca\ue5cb\ue5cc\ue5cd\ue5ce\ue5cf\ue5d0\ue5d1\ue5d2\ue5d3\ue5d4\ue5d5\u
 e5d6\ue5d7\ue5d8\ue5d9\ue5da\ue5db\ue5dc\ue5dd\ue5de\ue5df\ue5e0\ue5e1\ue5e2\ue5e3\ue5e4\ue5e5\ue5e6\ue5e7\ue5e8\ue5e9\ue5ea\ue5eb\ue5ec\ue5ed\ue5ee\ue5ef\ue5f0\ue5f1\ue5f2\ue5f3\ue5f4\ue5f5\ue5f6\ue5f7\ue5f8\ue5f9\ue5fa\ue5fb\ue5fc\ue5fd\ue5fe\ue5ff\ue600\ue601\ue602\ue603\ue604\ue605\ue606\ue607\ue608\ue609\ue60a\ue60b\ue60c\ue60d\ue60e\ue60f\ue610\ue611\ue612\ue613\ue614\ue615\ue616\ue617\ue618\ue619\ue61a\ue61b\ue61c\ue61d\ue61e\ue61f\ue620\ue621\ue622\ue623\ue624\ue625\ue626\ue627\ue628\ue629\ue62a\ue62b\ue62c\ue62d\ue62e\ue62f\ue630\ue631\ue632\ue633\ue634\ue635\ue636\ue637\ue638\ue639\ue63a\ue63b\ue63c\ue63d\ue63e\ue63f\ue640\ue641\ue642\ue643\ue644\ue645\ue646\ue647\ue648\ue649\ue64a\ue64b\ue64c\ue64d\ue64e\ue64f\ue650\ue651\ue652\ue653\ue654\ue655\ue656\ue657\ue658\ue659\ue65a\ue65b\ue65c\ue65d\ue65e\ue65f\ue660\ue661\ue662\ue663\ue664\ue665\ue666\ue667\ue668\ue669\ue66a\ue66b\ue66c\ue66d\ue66e\ue66f\ue670\ue671\ue672\ue673\ue674\ue675\ue676\ue677\ue678\ue679\ue67a\ue67b\ue
 67c\ue67d\ue67e\ue67f\ue680\ue681\ue682\ue683\ue684\ue685\ue686\ue687\ue688\ue689\ue68a\ue68b\ue68c\ue68d\ue68e\ue68f\ue690\ue691\ue692\ue693\ue694\ue695\ue696\ue697\ue698\ue699\ue69a\ue69b\ue69c\ue69d\ue69e\ue69f\ue6a0\ue6a1\ue6a2\ue6a3\ue6a4\ue6a5\ue6a6\ue6a7\ue6a8\ue6a9\ue6aa\ue6ab\ue6ac\ue6ad\ue6ae\ue6af\ue6b0\ue6b1\ue6b2\ue6b3\ue6b4\ue6b5\ue6b6\ue6b7\ue6b8\ue6b9\ue6ba\ue6bb\ue6bc\ue6bd\ue6be\ue6bf\ue6c0\ue6c1\ue6c2\ue6c3\ue6c4\ue6c5\ue6c6\ue6c7\ue6c8\ue6c9\ue6ca\ue6cb\ue6cc\ue6cd\ue6ce\ue6cf\ue6d0\ue6d1\ue6d2\ue6d3\ue6d4\ue6d5\ue6d6\ue6d7\ue6d8\ue6d9\ue6da\ue6db\ue6dc\ue6dd\ue6de\ue6df\ue6e0\ue6e1\ue6e2\ue6e3\ue6e4\ue6e5\ue6e6\ue6e7\ue6e8\ue6e9\ue6ea\ue6eb\ue6ec\ue6ed\ue6ee\ue6ef\ue6f0\ue6f1\ue6f2\ue6f3\ue6f4\ue6f5\ue6f6\ue6f7\ue6f8\ue6f9\ue6fa\ue6fb\ue6fc\ue6fd\ue6fe\ue6ff\ue700\ue701\ue702\ue703\ue704\ue705\ue706\ue707\ue708\ue709\ue70a\ue70b\ue70c\ue70d\ue70e\ue70f\ue710\ue711\ue712\ue713\ue714\ue715\ue716\ue717\ue718\ue719\ue71a\ue71b\ue71c\ue71d\ue71e\ue71f\ue720\ue721\ue7
 22\ue723\ue724\ue725\ue726\ue727\ue728\ue729\ue72a\ue72b\ue72c\ue72d\ue72e\ue72f\ue730\ue731\ue732\ue733\ue734\ue735\ue736\ue737\ue738\ue739\ue73a\ue73b\ue73c\ue73d\ue73e\ue73f\ue740\ue741\ue742\ue743\ue744\ue745\ue746\ue747\ue748\ue749\ue74a\ue74b\ue74c\ue74d\ue74e\ue74f\ue750\ue751\ue752\ue753\ue754\ue755\ue756\ue757\ue758\ue759\ue75a\ue75b\ue75c\ue75d\ue75e\ue75f\ue760\ue761\ue762\ue763\ue764\ue765\ue766\ue767\ue768\ue769\ue76a\ue76b\ue76c\ue76d\ue76e\ue76f\ue770\ue771\ue772\ue773\ue774\ue775\ue776\ue777\ue778\ue779\ue77a\ue77b\ue77c\ue77d\ue77e\ue77f\ue780\ue781\ue782\ue783\ue784\ue785\ue786\ue787\ue788\ue789\ue78a\ue78b\ue78c\ue78d\ue78e\ue78f\ue790\ue791\ue792\ue793\ue794\ue795\ue796\ue797\ue798\ue799\ue79a\ue79b\ue79c\ue79d\ue79e\ue79f\ue7a0\ue7a1\ue7a2\ue7a3\ue7a4\ue7a5\ue7a6\ue7a7\ue7a8\ue7a9\ue7aa\ue7ab\ue7ac\ue7ad\ue7ae\ue7af\ue7b0\ue7b1\ue7b2\ue7b3\ue7b4\ue7b5\ue7b6\ue7b7\ue7b8\ue7b9\ue7ba\ue7bb\ue7bc\ue7bd\ue7be\ue7bf\ue7c0\ue7c1\ue7c2\ue7c3\ue7c4\ue7c5\ue7c6\ue7c7\ue7c
 8\ue7c9\ue7ca\ue7cb\ue7cc\ue7cd\ue7ce\ue7cf\ue7d0\ue7d1\ue7d2\ue7d3\ue7d4\ue7d5\ue7d6\ue7d7\ue7d8\ue7d9\ue7da\ue7db\ue7dc\ue7dd\ue7de\ue7df\ue7e0\ue7e1\ue7e2\ue7e3\ue7e4\ue7e5\ue7e6\ue7e7\ue7e8\ue7e9\ue7ea\ue7eb\ue7ec\ue7ed\ue7ee\ue7ef\ue7f0\ue7f1\ue7f2\ue7f3\ue7f4\ue7f5\ue7f6\ue7f7\ue7f8\ue7f9\ue7fa\ue7fb\ue7fc\ue7fd\ue7fe\ue7ff\ue800\ue801\ue802\ue803\ue804\ue805\ue806\ue807\ue808\ue809\ue80a\ue80b\ue80c\ue80d\ue80e\ue80f\ue810\ue811\ue812\ue813\ue814\ue815\ue816\ue817\ue818\ue819\ue81a\ue81b\ue81c\ue81d\ue81e\ue81f\ue820\ue821\ue822\ue823\ue824\ue825\ue826\ue827\ue828\ue829\ue82a\ue82b\ue82c\ue82d\ue82e\ue82f\ue830\ue831\ue832\ue833\ue834\ue835\ue836\ue837\ue838\ue839\ue83a\ue83b\ue83c\ue83d\ue83e\ue83f\ue840\ue841\ue842\ue843\ue844\ue845\ue846\ue847\ue848\ue849\ue84a\ue84b\ue84c\ue84d\ue84e\ue84f\ue850\ue851\ue852\ue853\ue854\ue855\ue856\ue857\ue858\ue859\ue85a\ue85b\ue85c\ue85d\ue85e\ue85f\ue860\ue861\ue862\ue863\ue864\ue865\ue866\ue867\ue868\ue869\ue86a\ue86b\ue86c\ue86d\ue86e
 \ue86f\ue870\ue871\ue872\ue873\ue874\ue875\ue876\ue877\ue878\ue879\ue87a\ue87b\ue87c\ue87d\ue87e\ue87f\ue880\ue881\ue882\ue883\ue884\ue885\ue886\ue887\ue888\ue889\ue88a\ue88b\ue88c\ue88d\ue88e\ue88f\ue890\ue891\ue892\ue893\ue894\ue895\ue896\ue897\ue898\ue899\ue89a\ue89b\ue89c\ue89d\ue89e\ue89f\ue8a0\ue8a1\ue8a2\ue8a3\ue8a4\ue8a5\ue8a6\ue8a7\ue8a8\ue8a9\ue8aa\ue8ab\ue8ac\ue8ad\ue8ae\ue8af\ue8b0\ue8b1\ue8b2\ue8b3\ue8b4\ue8b5\ue8b6\ue8b7\ue8b8\ue8b9\ue8ba\ue8bb\ue8bc\ue8bd\ue8be\ue8bf\ue8c0\ue8c1\ue8c2\ue8c3\ue8c4\ue8c5\ue8c6\ue8c7\ue8c8\ue8c9\ue8ca\ue8cb\ue8cc\ue8cd\ue8ce\ue8cf\ue8d0\ue8d1\ue8d2\ue8d3\ue8d4\ue8d5\ue8d6\ue8d7\ue8d8\ue8d9\ue8da\ue8db\ue8dc\ue8dd\ue8de\ue8df\ue8e0\ue8e1\ue8e2\ue8e3\ue8e4\ue8e5\ue8e6\ue8e7\ue8e8\ue8e9\ue8ea\ue8eb\ue8ec\ue8ed\ue8ee\ue8ef\ue8f0\ue8f1\ue8f2\ue8f3\ue8f4\ue8f5\ue8f6\ue8f7\ue8f8\ue8f9\ue8fa\ue8fb\ue8fc\ue8fd\ue8fe\ue8ff\ue900\ue901\ue902\ue903\ue904\ue905\ue906\ue907\ue908\ue909\ue90a\ue90b\ue90c\ue90d\ue90e\ue90f\ue910\ue911\ue912\ue913\ue914\
 ue915\ue916\ue917\ue918\ue919\ue91a\ue91b\ue91c\ue91d\ue91e\ue91f\ue920\ue921\ue922\ue923\ue924\ue925\ue926\ue927\ue928\ue929\ue92a\ue92b\ue92c\ue92d\ue92e\ue92f\ue930\ue931\ue932\ue933\ue934\ue935\ue936\ue937\ue938\ue939\ue93a\ue93b\ue93c\ue93d\ue93e\ue93f\ue940\ue941\ue942\ue943\ue944\ue945\ue946\ue947\ue948\ue949\ue94a\ue94b\ue94c\ue94d\ue94e\ue94f\ue950\ue951\ue952\ue953\ue954\ue955\ue956\ue957\ue958\ue959\ue95a\ue95b\ue95c\ue95d\ue95e\ue95f\ue960\ue961\ue962\ue963\ue964\ue965\ue966\ue967\ue968\ue969\ue96a\ue96b\ue96c\ue96d\ue96e\ue96f\ue970\ue971\ue972\ue973\ue974\ue975\ue976\ue977\ue978\ue979\ue97a\ue97b\ue97c\ue97d\ue97e\ue97f\ue980\ue981\ue982\ue983\ue984\ue985\ue986\ue987\ue988\ue989\ue98a\ue98b\ue98c\ue98d\ue98e\ue98f\ue990\ue991\ue992\ue993\ue994\ue995\ue996\ue997\ue998\ue999\ue99a\ue99b\ue99c\ue99d\ue99e\ue99f\ue9a0\ue9a1\ue9a2\ue9a3\ue9a4\ue9a5\ue9a6\ue9a7\ue9a8\ue9a9\ue9aa\ue9ab\ue9ac\ue9ad\ue9ae\ue9af\ue9b0\ue9b1\ue9b2\ue9b3\ue9b4\ue9b5\ue9b6\ue9b7\ue9b8\ue9b9\ue9ba\u
 e9bb\ue9bc\ue9bd\ue9be\ue9bf\ue9c0\ue9c1\ue9c2\ue9c3\ue9c4\ue9c5\ue9c6\ue9c7\ue9c8\ue9c9\ue9ca\ue9cb\ue9cc\ue9cd\ue9ce\ue9cf\ue9d0\ue9d1\ue9d2\ue9d3\ue9d4\ue9d5\ue9d6\ue9d7\ue9d8\ue9d9\ue9da\ue9db\ue9dc\ue9dd\ue9de\ue9df\ue9e0\ue9e1\ue9e2\ue9e3\ue9e4\ue9e5\ue9e6\ue9e7\ue9e8\ue9e9\ue9ea\ue9eb\ue9ec\ue9ed\ue9ee\ue9ef\ue9f0\ue9f1\ue9f2\ue9f3\ue9f4\ue9f5\ue9f6\ue9f7\ue9f8\ue9f9\ue9fa\ue9fb\ue9fc\ue9fd\ue9fe\ue9ff\uea00\uea01\uea02\uea03\uea04\uea05\uea06\uea07\uea08\uea09\uea0a\uea0b\uea0c\uea0d\uea0e\uea0f\uea10\uea11\uea12\uea13\uea14\uea15\uea16\uea17\uea18\uea19\uea1a\uea1b\uea1c\uea1d\uea1e\uea1f\uea20\uea21\uea22\uea23\uea24\uea25\uea26\uea27\uea28\uea29\uea2a\uea2b\uea2c\uea2d\uea2e\uea2f\uea30\uea31\uea32\uea33\uea34\uea35\uea36\uea37\uea38\uea39\uea3a\uea3b\uea3c\uea3d\uea3e\uea3f\uea40\uea41\uea42\uea43\uea44\uea45\uea46\uea47\uea48\uea49\uea4a\uea4b\uea4c\uea4d\uea4e\uea4f\uea50\uea51\uea52\uea53\uea54\uea55\uea56\uea57\uea58\uea59\uea5a\uea5b\uea5c\uea5d\uea5e\uea5f\uea60\ue
 a61\uea62\uea63\uea64\uea65\uea66\uea67\uea68\uea69\uea6a\uea6b\uea6c\uea6d\uea6e\uea6f\uea70\uea71\uea72\uea73\uea74\uea75\uea76\uea77\uea78\uea79\uea7a\uea7b\uea7c\uea7d\uea7e\uea7f\uea80\uea81\uea82\uea83\uea84\uea85\uea86\uea87\uea88\uea89\uea8a\uea8b\uea8c\uea8d\uea8e\uea8f\uea90\uea91\uea92\uea93\uea94\uea95\uea96\uea97\uea98\uea99\uea9a\uea9b\uea9c\uea9d\uea9e\uea9f\ueaa0\ueaa1\ueaa2\ueaa3\ueaa4\ueaa5\ueaa6\ueaa7\ueaa8\ueaa9\ueaaa\ueaab\ueaac\ueaad\ueaae\ueaaf\ueab0\ueab1\ueab2\ueab3\ueab4\ueab5\ueab6\ueab7\ueab8\ueab9\ueaba\ueabb\ueabc\ueabd\ueabe\ueabf\ueac0\ueac1\ueac2\ueac3\ueac4\ueac5\ueac6\ueac7\ueac8\ueac9\ueaca\ueacb\ueacc\ueacd\ueace\ueacf\uead0\uead1\uead2\uead3\uead4\uead5\uead6\uead7\uead8\uead9\ueada\ueadb\ueadc\ueadd\ueade\ueadf\ueae0\ueae1\ueae2\ueae3\ueae4\ueae5\ueae6\ueae7\ueae8\ueae9\ueaea\ueaeb\ueaec\ueaed\ueaee\ueaef\ueaf0\ueaf1\ueaf2\ueaf3\ueaf4\ueaf5\ueaf6\ueaf7\ueaf8\ueaf9\ueafa\ueafb\ueafc\ueafd\ueafe\ueaff\ueb00\ueb01\ueb02\ueb03\ueb04\ueb05\ueb06\ueb
 07\ueb08\ueb09\ueb0a\ueb0b\ueb0c\ueb0d\ueb0e\ueb0f\ueb10\ueb11\ueb12\ueb13\ueb14\ueb15\ueb16\ueb17\ueb18\ueb19\ueb1a\ueb1b\ueb1c\ueb1d\ueb1e\ueb1f\ueb20\ueb21\ueb22\ueb23\ueb24\ueb25\ueb26\ueb27\ueb28\ueb29\ueb2a\ueb2b\ueb2c\ueb2d\ueb2e\ueb2f\ueb30\ueb31\ueb32\ueb33\ueb34\ueb35\ueb36\ueb37\ueb38\ueb39\ueb3a\ueb3b\ueb3c\ueb3d\ueb3e\ueb3f\ueb40\ueb41\ueb42\ueb43\ueb44\ueb45\ueb46\ueb47\ueb48\ueb49\ueb4a\ueb4b\ueb4c\ueb4d\ueb4e\ueb4f\ueb50\ueb51\ueb52\ueb53\ueb54\ueb55\ueb56\ueb57\ueb58\ueb59\ueb5a\ueb5b\ueb5c\ueb5d\ueb5e\ueb5f\ueb60\ueb61\ueb62\ueb63\ueb64\ueb65\ueb66\ueb67\ueb68\ueb69\ueb6a\ueb6b\ueb6c\ueb6d\ueb6e\ueb6f\ueb70\ueb71\ueb72\ueb73\ueb74\ueb75\ueb76\ueb77\ueb78\ueb79\ueb7a\ueb7b\ueb7c\ueb7d\ueb7e\ueb7f\ueb80\ueb81\ueb82\ueb83\ueb84\ueb85\ueb86\ueb87\ueb88\ueb89\ueb8a\ueb8b\ueb8c\ueb8d\ueb8e\ueb8f\ueb90\ueb91\ueb92\ueb93\ueb94\ueb95\ueb96\ueb97\ueb98\ueb99\ueb9a\ueb9b\ueb9c\ueb9d\ueb9e\ueb9f\ueba0\ueba1\ueba2\ueba3\ueba4\ueba5\ueba6\ueba7\ueba8\ueba9\uebaa\uebab\uebac\ueba
 d\uebae\uebaf\uebb0\uebb1\uebb2\uebb3\uebb4\uebb5\uebb6\uebb7\uebb8\uebb9\uebba\uebbb\uebbc\uebbd\uebbe\uebbf\uebc0\uebc1\uebc2\uebc3\uebc4\uebc5\uebc6\uebc7\uebc8\uebc9\uebca\uebcb\uebcc\uebcd\uebce\uebcf\uebd0\uebd1\uebd2\uebd3\uebd4\uebd5\uebd6\uebd7\uebd8\uebd9\uebda\uebdb\uebdc\uebdd\uebde\uebdf\uebe0\uebe1\uebe2\uebe3\uebe4\uebe5\uebe6\uebe7\uebe8\uebe9\uebea\uebeb\uebec\uebed\uebee\uebef\uebf0\uebf1\uebf2\uebf3\uebf4\uebf5\uebf6\uebf7\uebf8\uebf9\uebfa\uebfb\uebfc\uebfd\uebfe\uebff\uec00\uec01\uec02\uec03\uec04\uec05\uec06\uec07\uec08\uec09\uec0a\uec0b\uec0c\uec0d\uec0e\uec0f\uec10\uec11\uec12\uec13\uec14\uec15\uec16\uec17\uec18\uec19\uec1a\uec1b\uec1c\uec1d\uec1e\uec1f\uec20\uec21\uec22\uec23\uec24\uec25\uec26\uec27\uec28\uec29\uec2a\uec2b\uec2c\uec2d\uec2e\uec2f\uec30\uec31\uec32\uec33\uec34\uec35\uec36\uec37\uec38\uec39\uec3a\uec3b\uec3c\uec3d\uec3e\uec3f\uec40\uec41\uec42\uec43\uec44\uec45\uec46\uec47\uec48\uec49\uec4a\uec4b\uec4c\uec4d\uec4e\uec4f\uec50\uec51\uec52\uec53
 \uec54\uec55\uec56\uec57\uec58\uec59\uec5a\uec5b\uec5c\uec5d\uec5e\uec5f\uec60\uec61\uec62\uec63\uec64\uec65\uec66\uec67\uec68\uec69\uec6a\uec6b\uec6c\uec6d\uec6e\uec6f\uec70\uec71\uec72\uec73\uec74\uec75\uec76\uec77\uec78\uec79\uec7a\uec7b\uec7c\uec7d\uec7e\uec7f\uec80\uec81\uec82\uec83\uec84\uec85\uec86\uec87\uec88\uec89\uec8a\uec8b\uec8c\uec8d\uec8e\uec8f\uec90\uec91\uec92\uec93\uec94\uec95\uec96\uec97\uec98\uec99\uec9a\uec9b\uec9c\uec9d\uec9e\uec9f\ueca0\ueca1\ueca2\ueca3\ueca4\ueca5\ueca6\ueca7\ueca8\ueca9\uecaa\uecab\uecac\uecad\uecae\uecaf\uecb0\uecb1\uecb2\uecb3\uecb4\uecb5\uecb6\uecb7\uecb8\uecb9\uecba\uecbb\uecbc\uecbd\uecbe\uecbf\uecc0\uecc1\uecc2\uecc3\uecc4\uecc5\uecc6\uecc7\uecc8\uecc9\uecca\ueccb\ueccc\ueccd\uecce\ueccf\uecd0\uecd1\uecd2\uecd3\uecd4\uecd5\uecd6\uecd7\uecd8\uecd9\uecda\uecdb\uecdc\uecdd\uecde\uecdf\uece0\uece1\uece2\uece3\uece4\uece5\uece6\uece7\uece8\uece9\uecea\ueceb\uecec\ueced\uecee\uecef\uecf0\uecf1\uecf2\uecf3\uecf4\uecf5\uecf6\uecf7\uecf8\uecf9\
 uecfa\uecfb\uecfc\uecfd\uecfe\uecff\ued00\ued01\ued02\ued03\ued04\ued05\ued06\ued07\ued08\ued09\ued0a\ued0b\ued0c\ued0d\ued0e\ued0f\ued10\ued11\ued12\ued13\ued14\ued15\ued16\ued17\ued18\ued19\ued1a\ued1b\ued1c\ued1d\ued1e\ued1f\ued20\ued21\ued22\ued23\ued24\ued25\ued26\ued27\ued28\ued29\ued2a\ued2b\ued2c\ued2d\ued2e\ued2f\ued30\ued31\ued32\ued33\ued34\ued35\ued36\ued37\ued38\ued39\ued3a\ued3b\ued3c\ued3d\ued3e\ued3f\ued40\ued41\ued42\ued43\ued44\ued45\ued46\ued47\ued48\ued49\ued4a\ued4b\ued4c\ued4d\ued4e\ued4f\ued50\ued51\ued52\ued53\ued54\ued55\ued56\ued57\ued58\ued59\ued5a\ued5b\ued5c\ued5d\ued5e\ued5f\ued60\ued61\ued62\ued63\ued64\ued65\ued66\ued67\ued68\ued69\ued6a\ued6b\ued6c\ued6d\ued6e\ued6f\ued70\ued71\ued72\ued73\ued74\ued75\ued76\ued77\ued78\ued79\ued7a\ued7b\ued7c\ued7d\ued7e\ued7f\ued80\ued81\ued82\ued83\ued84\ued85\ued86\ued87\ued88\ued89\ued8a\ued8b\ued8c\ued8d\ued8e\ued8f\ued90\ued91\ued92\ued93\ued94\ued95\ued96\ued97\ued98\ued99\ued9a\ued9b\ued9c\ued9d\ued9e\ued9f\u
 eda0\ueda1\ueda2\ueda3\ueda4\ueda5\ueda6\ueda7\ueda8\ueda9\uedaa\uedab\uedac\uedad\uedae\uedaf\uedb0\uedb1\uedb2\uedb3\uedb4\uedb5\uedb6\uedb7\uedb8\uedb9\uedba\uedbb\uedbc\uedbd\uedbe\uedbf\uedc0\uedc1\uedc2\uedc3\uedc4\uedc5\uedc6\uedc7\uedc8\uedc9\uedca\uedcb\uedcc\uedcd\uedce\uedcf\uedd0\uedd1\uedd2\uedd3\uedd4\uedd5\uedd6\uedd7\uedd8\uedd9\uedda\ueddb\ueddc\ueddd\uedde\ueddf\uede0\uede1\uede2\uede3\uede4\uede5\uede6\uede7\uede8\uede9\uedea\uedeb\uedec\ueded\uedee\uedef\uedf0\uedf1\uedf2\uedf3\uedf4\uedf5\uedf6\uedf7\uedf8\uedf9\uedfa\uedfb\uedfc\uedfd\uedfe\uedff\uee00\uee01\uee02\uee03\uee04\uee05\uee06\uee07\uee08\uee09\uee0a\uee0b\uee0c\uee0d\uee0e\uee0f\uee10\uee11\uee12\uee13\uee14\uee15\uee16\uee17\uee18\uee19\uee1a\uee1b\uee1c\uee1d\uee1e\uee1f\uee20\uee21\uee22\uee23\uee24\uee25\uee26\uee27\uee28\uee29\uee2a\uee2b\uee2c\uee2d\uee2e\uee2f\uee30\uee31\uee32\uee33\uee34\uee35\uee36\uee37\uee38\uee39\uee3a\uee3b\uee3c\uee3d\uee3e\uee3f\uee40\uee41\uee42\uee43\uee44\uee45\ue
 e46\uee47\uee48\uee49\uee4a\uee4b\uee4c\uee4d\uee4e\uee4f\uee50\uee51\uee52\uee53\uee54\uee55\uee56\uee57\uee58\uee59\uee5a\uee5b\uee5c\uee5d\uee5e\uee5f\uee60\uee61\uee62\uee63\uee64\uee65\uee66\uee67\uee68\uee69\uee6a\uee6b\uee6c\uee6d\uee6e\uee6f\uee70\uee71\uee72\uee73\uee74\uee75\uee76\uee77\uee78\uee79\uee7a\uee7b\uee7c\uee7d\uee7e\uee7f\uee80\uee81\uee82\uee83\uee84\uee85\uee86\uee87\uee88\uee89\uee8a\uee8b\uee8c\uee8d\uee8e\uee8f\uee90\uee91\uee92\uee93\uee94\uee95\uee96\uee97\uee98\uee99\uee9a\uee9b\uee9c\uee9d\uee9e\uee9f\ueea0\ueea1\ueea2\ueea3\ueea4\ueea5\ueea6\ueea7\ueea8\ueea9\ueeaa\ueeab\ueeac\ueead\ueeae\ueeaf\ueeb0\ueeb1\ueeb2\ueeb3\ueeb4\ueeb5\ueeb6\ueeb7\ueeb8\ueeb9\ueeba\ueebb\ueebc\ueebd\ueebe\ueebf\ueec0\ueec1\ueec2\ueec3\ueec4\ueec5\ueec6\ueec7\ueec8\ueec9\ueeca\ueecb\ueecc\ueecd\ueece\ueecf\ueed0\ueed1\ueed2\ueed3\ueed4\ueed5\ueed6\ueed7\ueed8\ueed9\ueeda\ueedb\ueedc\ueedd\ueede\ueedf\ueee0\ueee1\ueee2\ueee3\ueee4\ueee5\ueee6\ueee7\ueee8\ueee9\ueeea\ueeeb\uee
 ec\ueeed\ueeee\ueeef\ueef0\ueef1\ueef2\ueef3\ueef4\ueef5\ueef6\ueef7\ueef8\ueef9\ueefa\ueefb\ueefc\ueefd\ueefe\ueeff\uef00\uef01\uef02\uef03\uef04\uef05\uef06\uef07\uef08\uef09\uef0a\uef0b\uef0c\uef0d\uef0e\uef0f\uef10\uef11\uef12\uef13\uef14\uef15\uef16\uef17\uef18\uef19\uef1a\uef1b\uef1c\uef1d\uef1e\uef1f\uef20\uef21\uef22\uef23\uef24\uef25\uef26\uef27\uef28\uef29\uef2a\uef2b\uef2c\uef2d\uef2e\uef2f\uef30\uef31\uef32\uef33\uef34\uef35\uef36\uef37\uef38\uef39\uef3a\uef3b\uef3c\uef3d\uef3e\uef3f\uef40\uef41\uef42\uef43\uef44\uef45\uef46\uef47\uef48\uef49\uef4a\uef4b\uef4c\uef4d\uef4e\uef4f\uef50\uef51\uef52\uef53\uef54\uef55\uef56\uef57\uef58\uef59\uef5a\uef5b\uef5c\uef5d\uef5e\uef5f\uef60\uef61\uef62\uef63\uef64\uef65\uef66\uef67\uef68\uef69\uef6a\uef6b\uef6c\uef6d\uef6e\uef6f\uef70\uef71\uef72\uef73\uef74\uef75\uef76\uef77\uef78\uef79\uef7a\uef7b\uef7c\uef7d\uef7e\uef7f\uef80\uef81\uef82\uef83\uef84\uef85\uef86\uef87\uef88\uef89\uef8a\uef8b\uef8c\uef8d\uef8e\uef8f\uef90\uef91\uef9
 2\uef93\uef94\uef95\uef96\uef97\uef98\uef99\uef9a\uef9b\uef9c\uef9d\uef9e\uef9f\uefa0\uefa1\uefa2\uefa3\uefa4\uefa5\uefa6\uefa7\uefa8\uefa9\uefaa\uefab\uefac\uefad\uefae\uefaf\uefb0\uefb1\uefb2\uefb3\uefb4\uefb5\uefb6\uefb7\uefb8\uefb9\uefba\uefbb\uefbc\uefbd\uefbe\uefbf\uefc0\uefc1\uefc2\uefc3\uefc4\uefc5\uefc6\uefc7\uefc8\uefc9\uefca\uefcb\uefcc\uefcd\uefce\uefcf\uefd0\uefd1\uefd2\uefd3\uefd4\uefd5\uefd6\uefd7\uefd8\uefd9\uefda\uefdb\uefdc\uefdd\uefde\uefdf\uefe0\uefe1\uefe2\uefe3\uefe4\uefe5\uefe6\uefe7\uefe8\uefe9\uefea\uefeb\uefec\uefed\uefee\uefef\ueff0\ueff1\ueff2\ueff3\ueff4\ueff5\ueff6\ueff7\ueff8\ueff9\ueffa\ueffb\ueffc\ueffd\ueffe\uefff\uf000\uf001\uf002\uf003\uf004\uf005\uf006\uf007\uf008\uf009\uf00a\uf00b\uf00c\uf00d\uf00e\uf00f\uf010\uf011\uf012\uf013\uf014\uf015\uf016\uf017\uf018\uf019\uf01a\uf01b\uf01c\uf01d\uf01e\uf01f\uf020\uf021\uf022\uf023\uf024\uf025\uf026\uf027\uf028\uf029\uf02a\uf02b\uf02c\uf02d\uf02e\uf02f\uf030\uf031\uf032\uf033\uf034\uf035\uf036\uf037\uf038
 \uf039\uf03a\uf03b\uf03c\uf03d\uf03e\uf03f\uf040\uf041\uf042\uf043\uf044\uf045\uf046\uf047\uf048\uf049\uf04a\uf04b\uf04c\uf04d\uf04e\uf04f\uf050\uf051\uf052\uf053\uf054\uf055\uf056\uf057\uf058\uf059\uf05a\uf05b\uf05c\uf05d\uf05e\uf05f\uf060\uf061\uf062\uf063\uf064\uf065\uf066\uf067\uf068\uf069\uf06a\uf06b\uf06c\uf06d\uf06e\uf06f\uf070\uf071\uf072\uf073\uf074\uf075\uf076\uf077\uf078\uf079\uf07a\uf07b\uf07c\uf07d\uf07e\uf07f\uf080\uf081\uf082\uf083\uf084\uf085\uf086\uf087\uf088\uf089\uf08a\uf08b\uf08c\uf08d\uf08e\uf08f\uf090\uf091\uf092\uf093\uf094\uf095\uf096\uf097\uf098\uf099\uf09a\uf09b\uf09c\uf09d\uf09e\uf09f\uf0a0\uf0a1\uf0a2\uf0a3\uf0a4\uf0a5\uf0a6\uf0a7\uf0a8\uf0a9\uf0aa\uf0ab\uf0ac\uf0ad\uf0ae\uf0af\uf0b0\uf0b1\uf0b2\uf0b3\uf0b4\uf0b5\uf0b6\uf0b7\uf0b8\uf0b9\uf0ba\uf0bb\uf0bc\uf0bd\uf0be\uf0bf\uf0c0\uf0c1\uf0c2\uf0c3\uf0c4\uf0c5\uf0c6\uf0c7\uf0c8\uf0c9\uf0ca\uf0cb\uf0cc\uf0cd\uf0ce\uf0cf\uf0d0\uf0d1\uf0d2\uf0d3\uf0d4\uf0d5\uf0d6\uf0d7\uf0d8\uf0d9\uf0da\uf0db\uf0dc\uf0dd\uf0de\
 uf0df\uf0e0\uf0e1\uf0e2\uf0e3\uf0e4\uf0e5\uf0e6\uf0e7\uf0e8\uf0e9\uf0ea\uf0eb\uf0ec\uf0ed\uf0ee\uf0ef\uf0f0\uf0f1\uf0f2\uf0f3\uf0f4\uf0f5\uf0f6\uf0f7\uf0f8\uf0f9\uf0fa\uf0fb\uf0fc\uf0fd\uf0fe\uf0ff\uf100\uf101\uf102\uf103\uf104\uf105\uf106\uf107\uf108\uf109\uf10a\uf10b\uf10c\uf10d\uf10e\uf10f\uf110\uf111\uf112\uf113\uf114\uf115\uf116\uf117\uf118\uf119\uf11a\uf11b\uf11c\uf11d\uf11e\uf11f\uf120\uf121\uf122\uf123\uf124\uf125\uf126\uf127\uf128\uf129\uf12a\uf12b\uf12c\uf12d\uf12e\uf12f\uf130\uf131\uf132\uf133\uf134\uf135\uf136\uf137\uf138\uf139\uf13a\uf13b\uf13c\uf13d\uf13e\uf13f\uf140\uf141\uf142\uf143\uf144\uf145\uf146\uf147\uf148\uf149\uf14a\uf14b\uf14c\uf14d\uf14e\uf14f\uf150\uf151\uf152\uf153\uf154\uf155\uf156\uf157\uf158\uf159\uf15a\uf15b\uf15c\uf15d\uf15e\uf15f\uf160\uf161\uf162\uf163\uf164\uf165\uf166\uf167\uf168\uf169\uf16a\uf16b\uf16c\uf16d\uf16e\uf16f\uf170\uf171\uf172\uf173\uf174\uf175\uf176\uf177\uf178\uf179\uf17a\uf17b\uf17c\uf17d\uf17e\uf17f\uf180\uf181\uf182\uf183\uf184\u
 f185\uf186\uf187\uf188\uf189\uf18a\uf18b\uf18c\uf18d\uf18e\uf18f\uf190\uf191\uf192\uf193\uf194\uf195\uf196\uf197\uf198\uf199\uf19a\uf19b\uf19c\uf19d\uf19e\uf19f\uf1a0\uf1a1\uf1a2\uf1a3\uf1a4\uf1a5\uf1a6\uf1a7\uf1a8\uf1a9\uf1aa\uf1ab\uf1ac\uf1ad\uf1ae\uf1af\uf1b0\uf1b1\uf1b2\uf1b3\uf1b4\uf1b5\uf1b6\uf1b7\uf1b8\uf1b9\uf1ba\uf1bb\uf1bc\uf1bd\uf1be\uf1bf\uf1c0\uf1c1\uf1c2\uf1c3\uf1c4\uf1c5\uf1c6\uf1c7\uf1c8\uf1c9\uf1ca\uf1cb\uf1cc\uf1cd\uf1ce\uf1cf\uf1d0\uf1d1\uf1d2\uf1d3\uf1d4\uf1d5\uf1d6\uf1d7\uf1d8\uf1d9\uf1da\uf1db\uf1dc\uf1dd\uf1de\uf1df\uf1e0\uf1e1\uf1e2\uf1e3\uf1e4\uf1e5\uf1e6\uf1e7\uf1e8\uf1e9\uf1ea\uf1eb\uf1ec\uf1ed\uf1ee\uf1ef\uf1f0\uf1f1\uf1f2\uf1f3\uf1f4\uf1f5\uf1f6\uf1f7\uf1f8\uf1f9\uf1fa\uf1fb\uf1fc\uf1fd\uf1fe\uf1ff\uf200\uf201\uf202\uf203\uf204\uf205\uf206\uf207\uf208\uf209\uf20a\uf20b\uf20c\uf20d\uf20e\uf20f\uf210\uf211\uf212\uf213\uf214\uf215\uf216\uf217\uf218\uf219\uf21a\uf21b\uf21c\uf21d\uf21e\uf21f\uf220\uf221\uf222\uf223\uf224\uf225\uf226\uf227\uf228\uf229\uf22a\uf
 22b\uf22c\uf22d\uf22e\uf22f\uf230\uf231\uf232\uf233\uf234\uf235\uf236\uf237\uf238\uf239\uf23a\uf23b\uf23c\uf23d\uf23e\uf23f\uf240\uf241\uf242\uf243\uf244\uf245\uf246\uf247\uf248\uf249\uf24a\uf24b\uf24c\uf24d\uf24e\uf24f\uf250\uf251\uf252\uf253\uf254\uf255\uf256\uf257\uf258\uf259\uf25a\uf25b\uf25c\uf25d\uf25e\uf25f\uf260\uf261\uf262\uf263\uf264\uf265\uf266\uf267\uf268\uf269\uf26a\uf26b\uf26c\uf26d\uf26e\uf26f\uf270\uf271\uf272\uf273\uf274\uf275\uf276\uf277\uf278\uf279\uf27a\uf27b\uf27c\uf27d\uf27e\uf27f\uf280\uf281\uf282\uf283\uf284\uf285\uf286\uf287\uf288\uf289\uf28a\uf28b\uf28c\uf28d\uf28e\uf28f\uf290\uf291\uf292\uf293\uf294\uf295\uf296\uf297\uf298\uf299\uf29a\uf29b\uf29c\uf29d\uf29e\uf29f\uf2a0\uf2a1\uf2a2\uf2a3\uf2a4\uf2a5\uf2a6\uf2a7\uf2a8\uf2a9\uf2aa\uf2ab\uf2ac\uf2ad\uf2ae\uf2af\uf2b0\uf2b1\uf2b2\uf2b3\uf2b4\uf2b5\uf2b6\uf2b7\uf2b8\uf2b9\uf2ba\uf2bb\uf2bc\uf2bd\uf2be\uf2bf\uf2c0\uf2c1\uf2c2\uf2c3\uf2c4\uf2c5\uf2c6\uf2c7\uf2c8\uf2c9\uf2ca\uf2cb\uf2cc\uf2cd\uf2ce\uf2cf\uf2d0\uf2
 d1\uf2d2\uf2d3\uf2d4\uf2d5\uf2d6\uf2d7\uf2d8\uf2d9\uf2da\uf2db\uf2dc\uf2dd\uf2de\uf2df\uf2e0\uf2e1\uf2e2\uf2e3\uf2e4\uf2e5\uf2e6\uf2e7\uf2e8\uf2e9\uf2ea\uf2eb\uf2ec\uf2ed\uf2ee\uf2ef\uf2f0\uf2f1\uf2f2\uf2f3\uf2f4\uf2f5\uf2f6\uf2f7\uf2f8\uf2f9\uf2fa\uf2fb\uf2fc\uf2fd\uf2fe\uf2ff\uf300\uf301\uf302\uf303\uf304\uf305\uf306\uf307\uf308\uf309\uf30a\uf30b\uf30c\uf30d\uf30e\uf30f\uf310\uf311\uf312\uf313\uf314\uf315\uf316\uf317\uf318\uf319\uf31a\uf31b\uf31c\uf31d\uf31e\uf31f\uf320\uf321\uf322\uf323\uf324\uf325\uf326\uf327\uf328\uf329\uf32a\uf32b\uf32c\uf32d\uf32e\uf32f\uf330\uf331\uf332\uf333\uf334\uf335\uf336\uf337\uf338\uf339\uf33a\uf33b\uf33c\uf33d\uf33e\uf33f\uf340\uf341\uf342\uf343\uf344\uf345\uf346\uf347\uf348\uf349\uf34a\uf34b\uf34c\uf34d\uf34e\uf34f\uf350\uf351\uf352\uf353\uf354\uf355\uf356\uf357\uf358\uf359\uf35a\uf35b\uf35c\uf35d\uf35e\uf35f\uf360\uf361\uf362\uf363\uf364\uf365\uf366\uf367\uf368\uf369\uf36a\uf36b\uf36c\uf36d\uf36e\uf36f\uf370\uf371\uf372\uf373\uf374\uf375\uf376\uf37
 7\uf378\uf379\uf37a\uf37b\uf37c\uf37d\uf37e\uf37f\uf380\uf381\uf382\uf383\uf384\uf385\uf386\uf387\uf388\uf389\uf38a\uf38b\uf38c\uf38d\uf38e\uf38f\uf390\uf391\uf392\uf393\uf394\uf395\uf396\uf397\uf398\uf399\uf39a\uf39b\uf39c\uf39d\uf39e\uf39f\uf3a0\uf3a1\uf3a2\uf3a3\uf3a4\uf3a5\uf3a6\uf3a7\uf3a8\uf3a9\uf3aa\uf3ab\uf3ac\uf3ad\uf3ae\uf3af\uf3b0\uf3b1\uf3b2\uf3b3\uf3b4\uf3b5\uf3b6\uf3b7\uf3b8\uf3b9\uf3ba\uf3bb\uf3bc\uf3bd\uf3be\uf3bf\uf3c0\uf3c1\uf3c2\uf3c3\uf3c4\uf3c5\uf3c6\uf3c7\uf3c8\uf3c9\uf3ca\uf3cb\uf3cc\uf3cd\uf3ce\uf3cf\uf3d0\uf3d1\uf3d2\uf3d3\uf3d4\uf3d5\uf3d6\uf3d7\uf3d8\uf3d9\uf3da\uf3db\uf3dc\uf3dd\uf3de\uf3df\uf3e0\uf3e1\uf3e2\uf3e3\uf3e4\uf3e5\uf3e6\uf3e7\uf3e8\uf3e9\uf3ea\uf3eb\uf3ec\uf3ed\uf3ee\uf3ef\uf3f0\uf3f1\uf3f2\uf3f3\uf3f4\uf3f5\uf3f6\uf3f7\uf3f8\uf3f9\uf3fa\uf3fb\uf3fc\uf3fd\uf3fe\uf3ff\uf400\uf401\uf402\uf403\uf404\uf405\uf406\uf407\uf408\uf409\uf40a\uf40b\uf40c\uf40d\uf40e\uf40f\uf410\uf411\uf412\uf413\uf414\uf415\uf416\uf417\uf418\uf419\uf41a\uf41b\uf41c\uf41d
 \uf41e\uf41f\uf420\uf421\uf422\uf423\uf424\uf425\uf426\uf427\uf428\uf429\uf42a\uf42b\uf42c\uf42d\uf42e\uf42f\uf430\uf431\uf432\uf433\uf434\uf435\uf436\uf437\uf438\uf439\uf43a\uf43b\uf43c\uf43d\uf43e\uf43f\uf440\uf441\uf442\uf443\uf444\uf445\uf446\uf447\uf448\uf449\uf44a\uf44b\uf44c\uf44d\uf44e\uf44f\uf450\uf451\uf452\uf453\uf454\uf455\uf456\uf457\uf458\uf459\uf45a\uf45b\uf45c\uf45d\uf45e\uf45f\uf460\uf461\uf462\uf463\uf464\uf465\uf466\uf467\uf468\uf469\uf46a\uf46b\uf46c\uf46d\uf46e\uf46f\uf470\uf471\uf472\uf473\uf474\uf475\uf476\uf477\uf478\uf479\uf47a\uf47b\uf47c\uf47d\uf47e\uf47f\uf480\uf481\uf482\uf483\uf484\uf485\uf486\uf487\uf488\uf489\uf48a\uf48b\uf48c\uf48d\uf48e\uf48f\uf490\uf491\uf492\uf493\uf494\uf495\uf496\uf497\uf498\uf499\uf49a\uf49b\uf49c\uf49d\uf49e\uf49f\uf4a0\uf4a1\uf4a2\uf4a3\uf4a4\uf4a5\uf4a6\uf4a7\uf4a8\uf4a9\uf4aa\uf4ab\uf4ac\uf4ad\uf4ae\uf4af\uf4b0\uf4b1\uf4b2\uf4b3\uf4b4\uf4b5\uf4b6\uf4b7\uf4b8\uf4b9\uf4ba\uf4bb\uf4bc\uf4bd\uf4be\uf4bf\uf4c0\uf4c1\uf4c2\uf4c3\
 uf4c4\uf4c5\uf4c6\uf4c7\uf4c8\uf4c9\uf4ca\uf4cb\uf4cc\uf4cd\uf4ce\uf4cf\uf4d0\uf4d1\uf4d2\uf4d3\uf4d4\uf4d5\uf4d6\uf4d7\uf4d8\uf4d9\uf4da\uf4db\uf4dc\uf4dd\uf4de\uf4df\uf4e0\uf4e1\uf4e2\uf4e3\uf4e4\uf4e5\uf4e6\uf4e7\uf4e8\uf4e9\uf4ea\uf4eb\uf4ec\uf4ed\uf4ee\uf4ef\uf4f0\uf4f1\uf4f2\uf4f3\uf4f4\uf4f5\uf4f6\uf4f7\uf4f8\uf4f9\uf4fa\uf4fb\uf4fc\uf4fd\uf4fe\uf4ff\uf500\uf501\uf502\uf503\uf504\uf505\uf506\uf507\uf508\uf509\uf50a\uf50b\uf50c\uf50d\uf50e\uf50f\uf510\uf511\uf512\uf513\uf514\uf515\uf516\uf517\uf518\uf519\uf51a\uf51b\uf51c\uf51d\uf51e\uf51f\uf520\uf521\uf522\uf523\uf524\uf525\uf526\uf527\uf528\uf529\uf52a\uf52b\uf52c\uf52d\uf52e\uf52f\uf530\uf531\uf532\uf533\uf534\uf535\uf536\uf537\uf538\uf539\uf53a\uf53b\uf53c\uf53d\uf53e\uf53f\uf540\uf541\uf542\uf543\uf544\uf545\uf546\uf547\uf548\uf549\uf54a\uf54b\uf54c\uf54d\uf54e\uf54f\uf550\uf551\uf552\uf553\uf554\uf555\uf556\uf557\uf558\uf559\uf55a\uf55b\uf55c\uf55d\uf55e\uf55f\uf560\uf561\uf562\uf563\uf564\uf565\uf566\uf567\uf568\uf569\u
 f56a\uf56b\uf56c\uf56d\uf56e\uf56f\uf570\uf571\uf572\uf573\uf574\uf575\uf576\uf577\uf578\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf582\uf583\uf584\uf585\uf586\uf587\uf588\uf589\uf58a\uf58b\uf58c\uf58d\uf58e\uf58f\uf590\uf591\uf592\uf593\uf594\uf595\uf596\uf597\uf598\uf599\uf59a\uf59b\uf59c\uf59d\uf59e\uf59f\uf5a0\uf5a1\uf5a2\uf5a3\uf5a4\uf5a5\uf5a6\uf5a7\uf5a8\uf5a9\uf5aa\uf5ab\uf5ac\uf5ad\uf5ae\uf5af\uf5b0\uf5b1\uf5b2\uf5b3\uf5b4\uf5b5\uf5b6\uf5b7\uf5b8\uf5b9\uf5ba\uf5bb\uf5bc\uf5bd\uf5be\uf5bf\uf5c0\uf5c1\uf5c2\uf5c3\uf5c4\uf5c5\uf5c6\uf5c7\uf5c8\uf5c9\uf5ca\uf5cb\uf5cc\uf5cd\uf5ce\uf5cf\uf5d0\uf5d1\uf5d2\uf5d3\uf5d4\uf5d5\uf5d6\uf5d7\uf5d8\uf5d9\uf5da\uf5db\uf5dc\uf5dd\uf5de\uf5df\uf5e0\uf5e1\uf5e2\uf5e3\uf5e4\uf5e5\uf5e6\uf5e7\uf5e8\uf5e9\uf5ea\uf5eb\uf5ec\uf5ed\uf5ee\uf5ef\uf5f0\uf5f1\uf5f2\uf5f3\uf5f4\uf5f5\uf5f6\uf5f7\uf5f8\uf5f9\uf5fa\uf5fb\uf5fc\uf5fd\uf5fe\uf5ff\uf600\uf601\uf602\uf603\uf604\uf605\uf606\uf607\uf608\uf609\uf60a\uf60b\uf60c\uf60d\uf60e\uf60f\uf
 610\uf611\uf612\uf613\uf614\uf615\uf616\uf617\uf618\uf619\uf61a\uf61b\uf61c\uf61d\uf61e\uf61f\uf620\uf621\uf622\uf623\uf624\uf625\uf626\uf627\uf628\uf629\uf62a\uf62b\uf62c\uf62d\uf62e\uf62f\uf630\uf631\uf632\uf633\uf634\uf635\uf636\uf637\uf638\uf639\uf63a\uf63b\uf63c\uf63d\uf63e\uf63f\uf640\uf641\uf642\uf643\uf644\uf645\uf646\uf647\uf648\uf649\uf64a\uf64b\uf64c\uf64d\uf64e\uf64f\uf650\uf651\uf652\uf653\uf654\uf655\uf656\uf657\uf658\uf659\uf65a\uf65b\uf65c\uf65d\uf65e\uf65f\uf660\uf661\uf662\uf663\uf664\uf665\uf666\uf667\uf668\uf669\uf66a\uf66b\uf66c\uf66d\uf66e\uf66f\uf670\uf671\uf672\uf673\uf674\uf675\uf676\uf677\uf678\uf679\uf67a\uf67b\uf67c\uf67d\uf67e\uf67f\uf680\uf681\uf682\uf683\uf684\uf685\uf686\uf687\uf688\uf689\uf68a\uf68b\uf68c\uf68d\uf68e\uf68f\uf690\uf691\uf692\uf693\uf694\uf695\uf696\uf697\uf698\uf699\uf69a\uf69b\uf69c\uf69d\uf69e\uf69f\uf6a0\uf6a1\uf6a2\uf6a3\uf6a4\uf6a5\uf6a6\uf6a7\uf6a8\uf6a9\uf6aa\uf6ab\uf6ac\uf6ad\uf6ae\uf6af\uf6b0\uf6b1\uf6b2\uf6b3\uf6b4\uf6b5\uf6
 b6\uf6b7\uf6b8\uf6b9\uf6ba\uf6bb\uf6bc\uf6bd\uf6be\uf6bf\uf6c0\uf6c1\uf6c2\uf6c3\uf6c4\uf6c5\uf6c6\uf6c7\uf6c8\uf6c9\uf6ca\uf6cb\uf6cc\uf6cd\uf6ce\uf6cf\uf6d0\uf6d1\uf6d2\uf6d3\uf6d4\uf6d5\uf6d6\uf6d7\uf6d8\uf6d9\uf6da\uf6db\uf6dc\uf6dd\uf6de\uf6df\uf6e0\uf6e1\uf6e2\uf6e3\uf6e4\uf6e5\uf6e6\uf6e7\uf6e8\uf6e9\uf6ea\uf6eb\uf6ec\uf6ed\uf6ee\uf6ef\uf6f0\uf6f1\uf6f2\uf6f3\uf6f4\uf6f5\uf6f6\uf6f7\uf6f8\uf6f9\uf6fa\uf6fb\uf6fc\uf6fd\uf6fe\uf6ff\uf700\uf701\uf702\uf703\uf704\uf705\uf706\uf707\uf708\uf709\uf70a\uf70b\uf70c\uf70d\uf70e\uf70f\uf710\uf711\uf712\uf713\uf714\uf715\uf716\uf717\uf718\uf719\uf71a\uf71b\uf71c\uf71d\uf71e\uf71f\uf720\uf721\uf722\uf723\uf724\uf725\uf726\uf727\uf728\uf729\uf72a\uf72b\uf72c\uf72d\uf72e\uf72f\uf730\uf731\uf732\uf733\uf734\uf735\uf736\uf737\uf738\uf739\uf73a\uf73b\uf73c\uf73d\uf73e\uf73f\uf740\uf741\uf742\uf743\uf744\uf745\uf746\uf747\uf748\uf749\uf74a\uf74b\uf74c\uf74d\uf74e\uf74f\uf750\uf751\uf752\uf753\uf754\uf755\uf756\uf757\uf758\uf759\uf75a\uf75b\uf75
 c\uf75d\uf75e\uf75f\uf760\uf761\uf762\uf763\uf764\uf765\uf766\uf767\uf768\uf769\uf76a\uf76b\uf76c\uf76d\uf76e\uf76f\uf770\uf771\uf772\uf773\uf774\uf775\uf776\uf777\uf778\uf779\uf77a\uf77b\uf77c\uf77d\uf77e\uf77f\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff\uf800\uf801\uf802
 \uf803\uf804\uf805\uf806\uf807\uf808\uf809\uf80a\uf80b\uf80c\uf80d\uf80e\uf80f\uf810\uf811\uf812\uf813\uf814\uf815\uf816\uf817\uf818\uf819\uf81a\uf81b\uf81c\uf81d\uf81e\uf81f\uf820\uf821\uf822\uf823\uf824\uf825\uf826\uf827\uf828\uf829\uf82a\uf82b\uf82c\uf82d\uf82e\uf82f\uf830\uf831\uf832\uf833\uf834\uf835\uf836\uf837\uf838\uf839\uf83a\uf83b\uf83c\uf83d\uf83e\uf83f\uf840\uf841\uf842\uf843\uf844\uf845\uf846\uf847\uf848\uf849\uf84a\uf84b\uf84c\uf84d\uf84e\uf84f\uf850\uf851\uf852\uf853\uf854\uf855\uf856\uf857\uf858\uf859\uf85a\uf85b\uf85c\uf85d\uf85e\uf85f\uf860\uf861\uf862\uf863\uf864\uf865\uf866\uf867\uf868\uf869\uf86a\uf86b\uf86c\uf86d\uf86e\uf86f\uf870\uf871\uf872\uf873\uf874\uf875\uf876\uf877\uf878\uf879\uf87a\uf87b\uf87c\uf87d\uf87e\uf87f\uf880\uf881\uf882\uf883\uf884\uf885\uf886\uf887\uf888\uf889\uf88a\uf88b\uf88c\uf88d\uf88e\uf88f\uf890\uf891\uf892\uf893\uf894\uf895\uf896\uf897\uf898\uf899\uf89a\uf89b\uf89c\uf89d\uf89e\uf89f\uf8a0\uf8a1\uf8a2\uf8a3\uf8a4\uf8a5\uf8a6\uf8a7\uf8a8\
 uf8a9\uf8aa\uf8ab\uf8ac\uf8ad\uf8ae\uf8af\uf8b0\uf8b1\uf8b2\uf8b3\uf8b4\uf8b5\uf8b6\uf8b7\uf8b8\uf8b9\uf8ba\uf8bb\uf8bc\uf8bd\uf8be\uf8bf\uf8c0\uf8c1\uf8c2\uf8c3\uf8c4\uf8c5\uf8c6\uf8c7\uf8c8\uf8c9\uf8ca\uf8cb\uf8cc\uf8cd\uf8ce\uf8cf\uf8d0\uf8d1\uf8d2\uf8d3\uf8d4\uf8d5\uf8d6\uf8d7\uf8d8\uf8d9\uf8da\uf8db\uf8dc\uf8dd\uf8de\uf8df\uf8e0\uf8e1\uf8e2\uf8e3\uf8e4\uf8e5\uf8e6\uf8e7\uf8e8\uf8e9\uf8ea\uf8eb\uf8ec\uf8ed\uf8ee\uf8ef\uf8f0\uf8f1\uf8f2\uf8f3\uf8f4\uf8f5\uf8f6\uf8f7\uf8f8\uf8f9\uf8fa\uf8fb\uf8fc\uf8fd\uf8fe\uf8ff'
+
+try:
+    Cs = eval(r"'\ud800\ud801\ud802\ud803\ud804\ud805\ud806\ud807\ud808\ud809\ud80a\ud80b\ud80c\ud80d\ud80e\ud80f\ud810\ud811\ud812\ud813\ud814\ud815\ud816\ud817\ud818\ud819\ud81a\ud81b\ud81c\ud81d\ud81e\ud81f\ud820\ud821\ud822\ud823\ud824\ud825\ud826\ud827\ud828\ud829\ud82a\ud82b\ud82c\ud82d\ud82e\ud82f\ud830\ud831\ud832\ud833\ud834\ud835\ud836\ud837\ud838\ud839\ud83a\ud83b\ud83c\ud83d\ud83e\ud83f\ud840\ud841\ud842\ud843\ud844\ud845\ud846\ud847\ud848\ud849\ud84a\ud84b\ud84c\ud84d\ud84e\ud84f\ud850\ud851\ud852\ud853\ud854\ud855\ud856\ud857\ud858\ud859\ud85a\ud85b\ud85c\ud85d\ud85e\ud85f\ud860\ud861\ud862\ud863\ud864\ud865\ud866\ud867\ud868\ud869\ud86a\ud86b\ud86c\ud86d\ud86e\ud86f\ud870\ud871\ud872\ud873\ud874\ud875\ud876\ud877\ud878\ud879\ud87a\ud87b\ud87c\ud87d\ud87e\ud87f\ud880\ud881\ud882\ud883\ud884\ud885\ud886\ud887\ud888\ud889\ud88a\ud88b\ud88c\ud88d\ud88e\ud88f\ud890\ud891\ud892\ud893\ud894\ud895\ud896\ud897\ud898\ud899\ud89a\ud89b\ud89c\ud89d\ud89e\ud89f\ud8a0\ud8a1\ud8a2\u
 d8a3\ud8a4\ud8a5\ud8a6\ud8a7\ud8a8\ud8a9\ud8aa\ud8ab\ud8ac\ud8ad\ud8ae\ud8af\ud8b0\ud8b1\ud8b2\ud8b3\ud8b4\ud8b5\ud8b6\ud8b7\ud8b8\ud8b9\ud8ba\ud8bb\ud8bc\ud8bd\ud8be\ud8bf\ud8c0\ud8c1\ud8c2\ud8c3\ud8c4\ud8c5\ud8c6\ud8c7\ud8c8\ud8c9\ud8ca\ud8cb\ud8cc\ud8cd\ud8ce\ud8cf\ud8d0\ud8d1\ud8d2\ud8d3\ud8d4\ud8d5\ud8d6\ud8d7\ud8d8\ud8d9\ud8da\ud8db\ud8dc\ud8dd\ud8de\ud8df\ud8e0\ud8e1\ud8e2\ud8e3\ud8e4\ud8e5\ud8e6\ud8e7\ud8e8\ud8e9\ud8ea\ud8eb\ud8ec\ud8ed\ud8ee\ud8ef\ud8f0\ud8f1\ud8f2\ud8f3\ud8f4\ud8f5\ud8f6\ud8f7\ud8f8\ud8f9\ud8fa\ud8fb\ud8fc\ud8fd\ud8fe\ud8ff\ud900\ud901\ud902\ud903\ud904\ud905\ud906\ud907\ud908\ud909\ud90a\ud90b\ud90c\ud90d\ud90e\ud90f\ud910\ud911\ud912\ud913\ud914\ud915\ud916\ud917\ud918\ud919\ud91a\ud91b\ud91c\ud91d\ud91e\ud91f\ud920\ud921\ud922\ud923\ud924\ud925\ud926\ud927\ud928\ud929\ud92a\ud92b\ud92c\ud92d\ud92e\ud92f\ud930\ud931\ud932\ud933\ud934\ud935\ud936\ud937\ud938\ud939\ud93a\ud93b\ud93c\ud93d\ud93e\ud93f\ud940\ud941\ud942\ud943\ud944\ud945\ud946\ud947\ud948\ud
 949\ud94a\ud94b\ud94c\ud94d\ud94e\ud94f\ud950\ud951\ud952\ud953\ud954\ud955\ud956\ud957\ud958\ud959\ud95a\ud95b\ud95c\ud95d\ud95e\ud95f\ud960\ud961\ud962\ud963\ud964\ud965\ud966\ud967\ud968\ud969\ud96a\ud96b\ud96c\ud96d\ud96e\ud96f\ud970\ud971\ud972\ud973\ud974\ud975\ud976\ud977\ud978\ud979\ud97a\ud97b\ud97c\ud97d\ud97e\ud97f\ud980\ud981\ud982\ud983\ud984\ud985\ud986\ud987\ud988\ud989\ud98a\ud98b\ud98c\ud98d\ud98e\ud98f\ud990\ud991\ud992\ud993\ud994\ud995\ud996\ud997\ud998\ud999\ud99a\ud99b\ud99c\ud99d\ud99e\ud99f\ud9a0\ud9a1\ud9a2\ud9a3\ud9a4\ud9a5\ud9a6\ud9a7\ud9a8\ud9a9\ud9aa\ud9ab\ud9ac\ud9ad\ud9ae\ud9af\ud9b0\ud9b1\ud9b2\ud9b3\ud9b4\ud9b5\ud9b6\ud9b7\ud9b8\ud9b9\ud9ba\ud9bb\ud9bc\ud9bd\ud9be\ud9bf\ud9c0\ud9c1\ud9c2\ud9c3\ud9c4\ud9c5\ud9c6\ud9c7\ud9c8\ud9c9\ud9ca\ud9cb\ud9cc\ud9cd\ud9ce\ud9cf\ud9d0\ud9d1\ud9d2\ud9d3\ud9d4\ud9d5\ud9d6\ud9d7\ud9d8\ud9d9\ud9da\ud9db\ud9dc\ud9dd\ud9de\ud9df\ud9e0\ud9e1\ud9e2\ud9e3\ud9e4\ud9e5\ud9e6\ud9e7\ud9e8\ud9e9\ud9ea\ud9eb\ud9ec\ud9ed\ud9ee\ud9
 ef\ud9f0\ud9f1\ud9f2\ud9f3\ud9f4\ud9f5\ud9f6\ud9f7\ud9f8\ud9f9\ud9fa\ud9fb\ud9fc\ud9fd\ud9fe\ud9ff\uda00\uda01\uda02\uda03\uda04\uda05\uda06\uda07\uda08\uda09\uda0a\uda0b\uda0c\uda0d\uda0e\uda0f\uda10\uda11\uda12\uda13\uda14\uda15\uda16\uda17\uda18\uda19\uda1a\uda1b\uda1c\uda1d\uda1e\uda1f\uda20\uda21\uda22\uda23\uda24\uda25\uda26\uda27\uda28\uda29\uda2a\uda2b\uda2c\uda2d\uda2e\uda2f\uda30\uda31\uda32\uda33\uda34\uda35\uda36\uda37\uda38\uda39\uda3a\uda3b\uda3c\uda3d\uda3e\uda3f\uda40\uda41\uda42\uda43\uda44\uda45\uda46\uda47\uda48\uda49\uda4a\uda4b\uda4c\uda4d\uda4e\uda4f\uda50\uda51\uda52\uda53\uda54\uda55\uda56\uda57\uda58\uda59\uda5a\uda5b\uda5c\uda5d\uda5e\uda5f\uda60\uda61\uda62\uda63\uda64\uda65\uda66\uda67\uda68\uda69\uda6a\uda6b\uda6c\uda6d\uda6e\uda6f\uda70\uda71\uda72\uda73\uda74\uda75\uda76\uda77\uda78\uda79\uda7a\uda7b\uda7c\uda7d\uda7e\uda7f\uda80\uda81\uda82\uda83\uda84\uda85\uda86\uda87\uda88\uda89\uda8a\uda8b\uda8c\uda8d\uda8e\uda8f\uda90\uda91\uda92\uda93\uda94\uda9
 5\uda96\uda97\uda98\uda99\uda9a\uda9b\uda9c\uda9d\uda9e\uda9f\udaa0\udaa1\udaa2\udaa3\udaa4\udaa5\udaa6\udaa7\udaa8\udaa9\udaaa\udaab\udaac\udaad\udaae\udaaf\udab0\udab1\udab2\udab3\udab4\udab5\udab6\udab7\udab8\udab9\udaba\udabb\udabc\udabd\udabe\udabf\udac0\udac1\udac2\udac3\udac4\udac5\udac6\udac7\udac8\udac9\udaca\udacb\udacc\udacd\udace\udacf\udad0\udad1\udad2\udad3\udad4\udad5\udad6\udad7\udad8\udad9\udada\udadb\udadc\udadd\udade\udadf\udae0\udae1\udae2\udae3\udae4\udae5\udae6\udae7\udae8\udae9\udaea\udaeb\udaec\udaed\udaee\udaef\udaf0\udaf1\udaf2\udaf3\udaf4\udaf5\udaf6\udaf7\udaf8\udaf9\udafa\udafb\udafc\udafd\udafe\udaff\udb00\udb01\udb02\udb03\udb04\udb05\udb06\udb07\udb08\udb09\udb0a\udb0b\udb0c\udb0d\udb0e\udb0f\udb10\udb11\udb12\udb13\udb14\udb15\udb16\udb17\udb18\udb19\udb1a\udb1b\udb1c\udb1d\udb1e\udb1f\udb20\udb21\udb22\udb23\udb24\udb25\udb26\udb27\udb28\udb29\udb2a\udb2b\udb2c\udb2d\udb2e\udb2f\udb30\udb31\udb32\udb33\udb34\udb35\udb36\udb37\udb38\udb39\udb3a\udb3b
 \udb3c\udb3d\udb3e\udb3f\udb40\udb41\udb42\udb43\udb44\udb45\udb46\udb47\udb48\udb49\udb4a\udb4b\udb4c\udb4d\udb4e\udb4f\udb50\udb51\udb52\udb53\udb54\udb55\udb56\udb57\udb58\udb59\udb5a\udb5b\udb5c\udb5d\udb5e\udb5f\udb60\udb61\udb62\udb63\udb64\udb65\udb66\udb67\udb68\udb69\udb6a\udb6b\udb6c\udb6d\udb6e\udb6f\udb70\udb71\udb72\udb73\udb74\udb75\udb76\udb77\udb78\udb79\udb7a\udb7b\udb7c\udb7d\udb7e\udb7f\udb80\udb81\udb82\udb83\udb84\udb85\udb86\udb87\udb88\udb89\udb8a\udb8b\udb8c\udb8d\udb8e\udb8f\udb90\udb91\udb92\udb93\udb94\udb95\udb96\udb97\udb98\udb99\udb9a\udb9b\udb9c\udb9d\udb9e\udb9f\udba0\udba1\udba2\udba3\udba4\udba5\udba6\udba7\udba8\udba9\udbaa\udbab\udbac\udbad\udbae\udbaf\udbb0\udbb1\udbb2\udbb3\udbb4\udbb5\udbb6\udbb7\udbb8\udbb9\udbba\udbbb\udbbc\udbbd\udbbe\udbbf\udbc0\udbc1\udbc2\udbc3\udbc4\udbc5\udbc6\udbc7\udbc8\udbc9\udbca\udbcb\udbcc\udbcd\udbce\udbcf\udbd0\udbd1\udbd2\udbd3\udbd4\udbd5\udbd6\udbd7\udbd8\udbd9\udbda\udbdb\udbdc\udbdd\udbde\udbdf\udbe0\udbe1\
 udbe2\udbe3\udbe4\udbe5\udbe6\udbe7\udbe8\udbe9\udbea\udbeb\udbec\udbed\udbee\udbef\udbf0\udbf1\udbf2\udbf3\udbf4\udbf5\udbf6\udbf7\udbf8\udbf9\udbfa\udbfb\udbfc\udbfd\udbfe\U0010fc00\udc01\udc02\udc03\udc04\udc05\udc06\udc07\udc08\udc09\udc0a\udc0b\udc0c\udc0d\udc0e\udc0f\udc10\udc11\udc12\udc13\udc14\udc15\udc16\udc17\udc18\udc19\udc1a\udc1b\udc1c\udc1d\udc1e\udc1f\udc20\udc21\udc22\udc23\udc24\udc25\udc26\udc27\udc28\udc29\udc2a\udc2b\udc2c\udc2d\udc2e\udc2f\udc30\udc31\udc32\udc33\udc34\udc35\udc36\udc37\udc38\udc39\udc3a\udc3b\udc3c\udc3d\udc3e\udc3f\udc40\udc41\udc42\udc43\udc44\udc45\udc46\udc47\udc48\udc49\udc4a\udc4b\udc4c\udc4d\udc4e\udc4f\udc50\udc51\udc52\udc53\udc54\udc55\udc56\udc57\udc58\udc59\udc5a\udc5b\udc5c\udc5d\udc5e\udc5f\udc60\udc61\udc62\udc63\udc64\udc65\udc66\udc67\udc68\udc69\udc6a\udc6b\udc6c\udc6d\udc6e\udc6f\udc70\udc71\udc72\udc73\udc74\udc75\udc76\udc77\udc78\udc79\udc7a\udc7b\udc7c\udc7d\udc7e\udc7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc
 88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff\udd00\udd01\udd02\udd03\udd04\udd05\udd06\udd07\udd08\udd09\udd0a\udd0b\udd0c\udd0d\udd0e\udd0f\udd10\udd11\udd12\udd13\udd14\udd15\udd16\udd17\udd18\udd19\udd1a\udd1b\udd1c\udd1d\udd1e\udd1f\udd20\udd21\udd22\udd23\udd24\udd25\udd26\udd27\udd28\udd29\udd2a\udd2b\udd2c\udd2d\udd2
 e\udd2f\udd30\udd31\udd32\udd33\udd34\udd35\udd36\udd37\udd38\udd39\udd3a\udd3b\udd3c\udd3d\udd3e\udd3f\udd40\udd41\udd42\udd43\udd44\udd45\udd46\udd47\udd48\udd49\udd4a\udd4b\udd4c\udd4d\udd4e\udd4f\udd50\udd51\udd52\udd53\udd54\udd55\udd56\udd57\udd58\udd59\udd5a\udd5b\udd5c\udd5d\udd5e\udd5f\udd60\udd61\udd62\udd63\udd64\udd65\udd66\udd67\udd68\udd69\udd6a\udd6b\udd6c\udd6d\udd6e\udd6f\udd70\udd71\udd72\udd73\udd74\udd75\udd76\udd77\udd78\udd79\udd7a\udd7b\udd7c\udd7d\udd7e\udd7f\udd80\udd81\udd82\udd83\udd84\udd85\udd86\udd87\udd88\udd89\udd8a\udd8b\udd8c\udd8d\udd8e\udd8f\udd90\udd91\udd92\udd93\udd94\udd95\udd96\udd97\udd98\udd99\udd9a\udd9b\udd9c\udd9d\udd9e\udd9f\udda0\udda1\udda2\udda3\udda4\udda5\udda6\udda7\udda8\udda9\uddaa\uddab\uddac\uddad\uddae\uddaf\uddb0\uddb1\uddb2\uddb3\uddb4\uddb5\uddb6\uddb7\uddb8\uddb9\uddba\uddbb\uddbc\uddbd\uddbe\uddbf\uddc0\uddc1\uddc2\uddc3\uddc4\uddc5\uddc6\uddc7\uddc8\uddc9\uddca\uddcb\uddcc\uddcd\uddce\uddcf\uddd0\uddd1\uddd2\uddd3\uddd4
 \uddd5\uddd6\uddd7\uddd8\uddd9\uddda\udddb\udddc\udddd\uddde\udddf\udde0\udde1\udde2\udde3\udde4\udde5\udde6\udde7\udde8\udde9\uddea\uddeb\uddec\udded\uddee\uddef\uddf0\uddf1\uddf2\uddf3\uddf4\uddf5\uddf6\uddf7\uddf8\uddf9\uddfa\uddfb\uddfc\uddfd\uddfe\uddff\ude00\ude01\ude02\ude03\ude04\ude05\ude06\ude07\ude08\ude09\ude0a\ude0b\ude0c\ude0d\ude0e\ude0f\ude10\ude11\ude12\ude13\ude14\ude15\ude16\ude17\ude18\ude19\ude1a\ude1b\ude1c\ude1d\ude1e\ude1f\ude20\ude21\ude22\ude23\ude24\ude25\ude26\ude27\ude28\ude29\ude2a\ude2b\ude2c\ude2d\ude2e\ude2f\ude30\ude31\ude32\ude33\ude34\ude35\ude36\ude37\ude38\ude39\ude3a\ude3b\ude3c\ude3d\ude3e\ude3f\ude40\ude41\ude42\ude43\ude44\ude45\ude46\ude47\ude48\ude49\ude4a\ude4b\ude4c\ude4d\ude4e\ude4f\ude50\ude51\ude52\ude53\ude54\ude55\ude56\ude57\ude58\ude59\ude5a\ude5b\ude5c\ude5d\ude5e\ude5f\ude60\ude61\ude62\ude63\ude64\ude65\ude66\ude67\ude68\ude69\ude6a\ude6b\ude6c\ude6d\ude6e\ude6f\ude70\ude71\ude72\ude73\ude74\ude75\ude76\ude77\ude78\ude79\ude7a\
 ude7b\ude7c\ude7d\ude7e\ude7f\ude80\ude81\ude82\ude83\ude84\ude85\ude86\ude87\ude88\ude89\ude8a\ude8b\ude8c\ude8d\ude8e\ude8f\ude90\ude91\ude92\ude93\ude94\ude95\ude96\ude97\ude98\ude99\ude9a\ude9b\ude9c\ude9d\ude9e\ude9f\udea0\udea1\udea2\udea3\udea4\udea5\udea6\udea7\udea8\udea9\udeaa\udeab\udeac\udead\udeae\udeaf\udeb0\udeb1\udeb2\udeb3\udeb4\udeb5\udeb6\udeb7\udeb8\udeb9\udeba\udebb\udebc\udebd\udebe\udebf\udec0\udec1\udec2\udec3\udec4\udec5\udec6\udec7\udec8\udec9\udeca\udecb\udecc\udecd\udece\udecf\uded0\uded1\uded2\uded3\uded4\uded5\uded6\uded7\uded8\uded9\udeda\udedb\udedc\udedd\udede\udedf\udee0\udee1\udee2\udee3\udee4\udee5\udee6\udee7\udee8\udee9\udeea\udeeb\udeec\udeed\udeee\udeef\udef0\udef1\udef2\udef3\udef4\udef5\udef6\udef7\udef8\udef9\udefa\udefb\udefc\udefd\udefe\udeff\udf00\udf01\udf02\udf03\udf04\udf05\udf06\udf07\udf08\udf09\udf0a\udf0b\udf0c\udf0d\udf0e\udf0f\udf10\udf11\udf12\udf13\udf14\udf15\udf16\udf17\udf18\udf19\udf1a\udf1b\udf1c\udf1d\udf1e\udf1f\udf20\u
 df21\udf22\udf23\udf24\udf25\udf26\udf27\udf28\udf29\udf2a\udf2b\udf2c\udf2d\udf2e\udf2f\udf30\udf31\udf32\udf33\udf34\udf35\udf36\udf37\udf38\udf39\udf3a\udf3b\udf3c\udf3d\udf3e\udf3f\udf40\udf41\udf42\udf43\udf44\udf45\udf46\udf47\udf48\udf49\udf4a\udf4b\udf4c\udf4d\udf4e\udf4f\udf50\udf51\udf52\udf53\udf54\udf55\udf56\udf57\udf58\udf59\udf5a\udf5b\udf5c\udf5d\udf5e\udf5f\udf60\udf61\udf62\udf63\udf64\udf65\udf66\udf67\udf68\udf69\udf6a\udf6b\udf6c\udf6d\udf6e\udf6f\udf70\udf71\udf72\udf73\udf74\udf75\udf76\udf77\udf78\udf79\udf7a\udf7b\udf7c\udf7d\udf7e\udf7f\udf80\udf81\udf82\udf83\udf84\udf85\udf86\udf87\udf88\udf89\udf8a\udf8b\udf8c\udf8d\udf8e\udf8f\udf90\udf91\udf92\udf93\udf94\udf95\udf96\udf97\udf98\udf99\udf9a\udf9b\udf9c\udf9d\udf9e\udf9f\udfa0\udfa1\udfa2\udfa3\udfa4\udfa5\udfa6\udfa7\udfa8\udfa9\udfaa\udfab\udfac\udfad\udfae\udfaf\udfb0\udfb1\udfb2\udfb3\udfb4\udfb5\udfb6\udfb7\udfb8\udfb9\udfba\udfbb\udfbc\udfbd\udfbe\udfbf\udfc0\udfc1\udfc2\udfc3\udfc4\udfc5\udfc6\ud
 fc7\udfc8\udfc9\udfca\udfcb\udfcc\udfcd\udfce\udfcf\udfd0\udfd1\udfd2\udfd3\udfd4\udfd5\udfd6\udfd7\udfd8\udfd9\udfda\udfdb\udfdc\udfdd\udfde\udfdf\udfe0\udfe1\udfe2\udfe3\udfe4\udfe5\udfe6\udfe7\udfe8\udfe9\udfea\udfeb\udfec\udfed\udfee\udfef\udff0\udff1\udff2\udff3\udff4\udff5\udff6\udff7\udff8\udff9\udffa\udffb\udffc\udffd\udffe\udfff'")
+except UnicodeDecodeError:
+    Cs = '' # Jython can't handle isolated surrogates
+
+Ll = u'abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u
 0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u0234\u0235\u0236\u0237\u0238\u0239\u023c\u023f\u0240\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d\u028e\u028f\u0290\u0291\u0292\u0293\u0294\u0295\u0296\u0297\u0298\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac\u02ad\u02ae\u02af\u0390\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u0
 3ef\u03f0\u03f1\u03f2\u03f3\u03f5\u03f8\u03fb\u03fc\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0561\u0562\u0563\u0564\u0565\u0566\u0567\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b\u057c\u057d\u05
 7e\u057f\u0580\u0581\u0582\u0583\u0584\u0585\u0586\u0587\u1d00\u1d01\u1d02\u1d03\u1d04\u1d05\u1d06\u1d07\u1d08\u1d09\u1d0a\u1d0b\u1d0c\u1d0d\u1d0e\u1d0f\u1d10\u1d11\u1d12\u1d13\u1d14\u1d15\u1d16\u1d17\u1d18\u1d19\u1d1a\u1d1b\u1d1c\u1d1d\u1d1e\u1d1f\u1d20\u1d21\u1d22\u1d23\u1d24\u1d25\u1d26\u1d27\u1d28\u1d29\u1d2a\u1d2b\u1d62\u1d63\u1d64\u1d65\u1d66\u1d67\u1d68\u1d69\u1d6a\u1d6b\u1d6c\u1d6d\u1d6e\u1d6f\u1d70\u1d71\u1d72\u1d73\u1d74\u1d75\u1d76\u1d77\u1d79\u1d7a\u1d7b\u1d7c\u1d7d\u1d7e\u1d7f\u1d80\u1d81\u1d82\u1d83\u1d84\u1d85\u1d86\u1d87\u1d88\u1d89\u1d8a\u1d8b\u1d8c\u1d8d\u1d8e\u1d8f\u1d90\u1d91\u1d92\u1d93\u1d94\u1d95\u1d96\u1d97\u1d98\u1d99\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e7
 1\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98\u1e99\u1e9a\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6\u1fb7
 \u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1ff7\

<TRUNCATED>

[27/59] [abbrv] git commit: AMBARI-7144. On Enable HA on a 3 node cluster - popup on warning for NN and SNN on same node appears.

Posted by nc...@apache.org.
AMBARI-7144. On Enable HA on a 3 node cluster - popup on warning for NN and SNN on same node appears.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7490cfda
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7490cfda
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7490cfda

Branch: refs/heads/branch-alerts-dev
Commit: 7490cfdaf72d4f323edb40179c57266d8e18acfe
Parents: ce77f0e
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Wed Sep 3 17:55:24 2014 -0700
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Wed Sep 3 17:55:30 2014 -0700

----------------------------------------------------------------------
 .../resources/stacks/HDP/2.0.6/services/stack_advisor.py     | 8 --------
 .../test/python/stacks/2.0.6/common/test_stack_advisor.py    | 4 +---
 2 files changed, 1 insertion(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7490cfda/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
index dd4fae3..d5be339 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
@@ -37,14 +37,6 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     nameNodeHosts = [component["StackServiceComponents"]["hostnames"] for component in componentsList if component["StackServiceComponents"]["component_name"] == "NAMENODE"]
     secondaryNameNodeHosts = [component["StackServiceComponents"]["hostnames"] for component in componentsList if component["StackServiceComponents"]["component_name"] == "SECONDARY_NAMENODE"]
 
-    if hostsCount > 1 and len(nameNodeHosts) > 0 and len(secondaryNameNodeHosts) > 0:
-      nameNodeHosts = nameNodeHosts[0]
-      secondaryNameNodeHosts = secondaryNameNodeHosts[0]
-      commonHosts = list(set(nameNodeHosts).intersection(secondaryNameNodeHosts))
-      for host in commonHosts:
-        items.append( { "type": 'host-component', "level": 'WARN', "message": 'NameNode and Secondary NameNode should not be hosted on same machine', "component-name": 'NAMENODE', "host": str(host) } )
-        items.append( { "type": 'host-component', "level": 'WARN', "message": 'NameNode and Secondary NameNode should not be hosted on same machine', "component-name": 'SECONDARY_NAMENODE', "host": str(host) } )
-
     # Validating cardinality
     for component in componentsList:
       if component["StackServiceComponents"]["cardinality"] is not None:

http://git-wip-us.apache.org/repos/asf/ambari/blob/7490cfda/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
index aa86242..510b439 100644
--- a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
@@ -85,7 +85,7 @@ class TestHDP206StackAdvisor(TestCase):
     }
     self.assertHostLayout(expectedComponentsHostsMap, result)
 
-  def test_validationNamenodeAndSecondaryNamenode2Hosts(self):
+  def test_validationNamenodeAndSecondaryNamenode2Hosts_noMessagesForSameHost(self):
     servicesInfo = [
       {
         "name": "HDFS",
@@ -99,8 +99,6 @@ class TestHDP206StackAdvisor(TestCase):
     result = self.stackAdvisor.validateComponentLayout(services, hosts)
 
     expectedItems = [
-      {"message": "NameNode and Secondary NameNode should not be hosted on same machine", "level": "WARN", "host": "host1"},
-      {"message": "NameNode and Secondary NameNode should not be hosted on same machine", "level": "WARN", "host": "host1"},
       {"message": "Host is not used", "level": "ERROR", "host": "host2"}
     ]
     self.assertValidationResult(expectedItems, result)


[19/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py
deleted file mode 100644
index b3d6bc7..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py
+++ /dev/null
@@ -1,1118 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.environment
-    ~~~~~~~~~~~~~~~~~~
-
-    Provides a class that holds runtime and parsing time options.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-from ambari_jinja2 import nodes
-from ambari_jinja2.defaults import *
-from ambari_jinja2.lexer import get_lexer, TokenStream
-from ambari_jinja2.parser import Parser
-from ambari_jinja2.optimizer import optimize
-from ambari_jinja2.compiler import generate
-from ambari_jinja2.runtime import Undefined, new_context
-from ambari_jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
-     TemplatesNotFound
-from ambari_jinja2.utils import import_string, LRUCache, Markup, missing, \
-     concat, consume, internalcode, _encode_filename
-
-
-# for direct template usage we have up to ten living environments
-_spontaneous_environments = LRUCache(10)
-
-# the function to create jinja traceback objects.  This is dynamically
-# imported on the first exception in the exception handler.
-_make_traceback = None
-
-
-def get_spontaneous_environment(*args):
-    """Return a new spontaneous environment.  A spontaneous environment is an
-    unnamed and unaccessible (in theory) environment that is used for
-    templates generated from a string and not from the file system.
-    """
-    try:
-        env = _spontaneous_environments.get(args)
-    except TypeError:
-        return Environment(*args)
-    if env is not None:
-        return env
-    _spontaneous_environments[args] = env = Environment(*args)
-    env.shared = True
-    return env
-
-
-def create_cache(size):
-    """Return the cache class for the given size."""
-    if size == 0:
-        return None
-    if size < 0:
-        return {}
-    return LRUCache(size)
-
-
-def copy_cache(cache):
-    """Create an empty copy of the given cache."""
-    if cache is None:
-        return None
-    elif type(cache) is dict:
-        return {}
-    return LRUCache(cache.capacity)
-
-
-def load_extensions(environment, extensions):
-    """Load the extensions from the list and bind it to the environment.
-    Returns a dict of instanciated environments.
-    """
-    result = {}
-    for extension in extensions:
-        if isinstance(extension, basestring):
-            extension = import_string(extension)
-        result[extension.identifier] = extension(environment)
-    return result
-
-
-def _environment_sanity_check(environment):
-    """Perform a sanity check on the environment."""
-    assert issubclass(environment.undefined, Undefined), 'undefined must ' \
-           'be a subclass of undefined because filters depend on it.'
-    assert environment.block_start_string != \
-           environment.variable_start_string != \
-           environment.comment_start_string, 'block, variable and comment ' \
-           'start strings must be different'
-    assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
-           'newline_sequence set to unknown line ending string.'
-    return environment
-
-
-class Environment(object):
-    r"""The core component of Jinja is the `Environment`.  It contains
-    important shared variables like configuration, filters, tests,
-    globals and others.  Instances of this class may be modified if
-    they are not shared and if no template was loaded so far.
-    Modifications on environments after the first template was loaded
-    will lead to surprising effects and undefined behavior.
-
-    Here the possible initialization parameters:
-
-        `block_start_string`
-            The string marking the begin of a block.  Defaults to ``'{%'``.
-
-        `block_end_string`
-            The string marking the end of a block.  Defaults to ``'%}'``.
-
-        `variable_start_string`
-            The string marking the begin of a print statement.
-            Defaults to ``'{{'``.
-
-        `variable_end_string`
-            The string marking the end of a print statement.  Defaults to
-            ``'}}'``.
-
-        `comment_start_string`
-            The string marking the begin of a comment.  Defaults to ``'{#'``.
-
-        `comment_end_string`
-            The string marking the end of a comment.  Defaults to ``'#}'``.
-
-        `line_statement_prefix`
-            If given and a string, this will be used as prefix for line based
-            statements.  See also :ref:`line-statements`.
-
-        `line_comment_prefix`
-            If given and a string, this will be used as prefix for line based
-            based comments.  See also :ref:`line-statements`.
-
-            .. versionadded:: 2.2
-
-        `trim_blocks`
-            If this is set to ``True`` the first newline after a block is
-            removed (block, not variable tag!).  Defaults to `False`.
-
-        `newline_sequence`
-            The sequence that starts a newline.  Must be one of ``'\r'``,
-            ``'\n'`` or ``'\r\n'``.  The default is ``'\n'`` which is a
-            useful default for Linux and OS X systems as well as web
-            applications.
-
-        `extensions`
-            List of Jinja extensions to use.  This can either be import paths
-            as strings or extension classes.  For more information have a
-            look at :ref:`the extensions documentation <jinja-extensions>`.
-
-        `optimized`
-            should the optimizer be enabled?  Default is `True`.
-
-        `undefined`
-            :class:`Undefined` or a subclass of it that is used to represent
-            undefined values in the template.
-
-        `finalize`
-            A callable that can be used to process the result of a variable
-            expression before it is output.  For example one can convert
-            `None` implicitly into an empty string here.
-
-        `autoescape`
-            If set to true the XML/HTML autoescaping feature is enabled by
-            default.  For more details about auto escaping see
-            :class:`~ambari_jinja2.utils.Markup`.  As of Jinja 2.4 this can also
-            be a callable that is passed the template name and has to
-            return `True` or `False` depending on autoescape should be
-            enabled by default.
-
-            .. versionchanged:: 2.4
-               `autoescape` can now be a function
-
-        `loader`
-            The template loader for this environment.
-
-        `cache_size`
-            The size of the cache.  Per default this is ``50`` which means
-            that if more than 50 templates are loaded the loader will clean
-            out the least recently used template.  If the cache size is set to
-            ``0`` templates are recompiled all the time, if the cache size is
-            ``-1`` the cache will not be cleaned.
-
-        `auto_reload`
-            Some loaders load templates from locations where the template
-            sources may change (ie: file system or database).  If
-            `auto_reload` is set to `True` (default) every time a template is
-            requested the loader checks if the source changed and if yes, it
-            will reload the template.  For higher performance it's possible to
-            disable that.
-
-        `bytecode_cache`
-            If set to a bytecode cache object, this object will provide a
-            cache for the internal Jinja bytecode so that templates don't
-            have to be parsed if they were not changed.
-
-            See :ref:`bytecode-cache` for more information.
-    """
-
-    #: if this environment is sandboxed.  Modifying this variable won't make
-    #: the environment sandboxed though.  For a real sandboxed environment
-    #: have a look at ambari_jinja2.sandbox
-    sandboxed = False
-
-    #: True if the environment is just an overlay
-    overlayed = False
-
-    #: the environment this environment is linked to if it is an overlay
-    linked_to = None
-
-    #: shared environments have this set to `True`.  A shared environment
-    #: must not be modified
-    shared = False
-
-    #: these are currently EXPERIMENTAL undocumented features.
-    exception_handler = None
-    exception_formatter = None
-
-    def __init__(self,
-                 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,
-                 line_statement_prefix=LINE_STATEMENT_PREFIX,
-                 line_comment_prefix=LINE_COMMENT_PREFIX,
-                 trim_blocks=TRIM_BLOCKS,
-                 newline_sequence=NEWLINE_SEQUENCE,
-                 extensions=(),
-                 optimized=True,
-                 undefined=Undefined,
-                 finalize=None,
-                 autoescape=False,
-                 loader=None,
-                 cache_size=50,
-                 auto_reload=True,
-                 bytecode_cache=None):
-        # !!Important notice!!
-        #   The constructor accepts quite a few arguments that should be
-        #   passed by keyword rather than position.  However it's important to
-        #   not change the order of arguments because it's used at least
-        #   internally in those cases:
-        #       -   spontaneus environments (i18n extension and Template)
-        #       -   unittests
-        #   If parameter changes are required only add parameters at the end
-        #   and don't change the arguments (or the defaults!) of the arguments
-        #   existing already.
-
-        # lexer / parser information
-        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.line_statement_prefix = line_statement_prefix
-        self.line_comment_prefix = line_comment_prefix
-        self.trim_blocks = trim_blocks
-        self.newline_sequence = newline_sequence
-
-        # runtime information
-        self.undefined = undefined
-        self.optimized = optimized
-        self.finalize = finalize
-        self.autoescape = autoescape
-
-        # defaults
-        self.filters = DEFAULT_FILTERS.copy()
-        self.tests = DEFAULT_TESTS.copy()
-        self.globals = DEFAULT_NAMESPACE.copy()
-
-        # set the loader provided
-        self.loader = loader
-        self.bytecode_cache = None
-        self.cache = create_cache(cache_size)
-        self.bytecode_cache = bytecode_cache
-        self.auto_reload = auto_reload
-
-        # load extensions
-        self.extensions = load_extensions(self, extensions)
-
-        _environment_sanity_check(self)
-
-    def add_extension(self, extension):
-        """Adds an extension after the environment was created.
-
-        .. versionadded:: 2.5
-        """
-        self.extensions.update(load_extensions(self, [extension]))
-
-    def extend(self, **attributes):
-        """Add the items to the instance of the environment if they do not exist
-        yet.  This is used by :ref:`extensions <writing-extensions>` to register
-        callbacks and configuration values without breaking inheritance.
-        """
-        for key, value in attributes.iteritems():
-            if not hasattr(self, key):
-                setattr(self, key, value)
-
-    def overlay(self, block_start_string=missing, block_end_string=missing,
-                variable_start_string=missing, variable_end_string=missing,
-                comment_start_string=missing, comment_end_string=missing,
-                line_statement_prefix=missing, line_comment_prefix=missing,
-                trim_blocks=missing, extensions=missing, optimized=missing,
-                undefined=missing, finalize=missing, autoescape=missing,
-                loader=missing, cache_size=missing, auto_reload=missing,
-                bytecode_cache=missing):
-        """Create a new overlay environment that shares all the data with the
-        current environment except of cache and the overridden attributes.
-        Extensions cannot be removed for an overlayed environment.  An overlayed
-        environment automatically gets all the extensions of the environment it
-        is linked to plus optional extra extensions.
-
-        Creating overlays should happen after the initial environment was set
-        up completely.  Not all attributes are truly linked, some are just
-        copied over so modifications on the original environment may not shine
-        through.
-        """
-        args = dict(locals())
-        del args['self'], args['cache_size'], args['extensions']
-
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.overlayed = True
-        rv.linked_to = self
-
-        for key, value in args.iteritems():
-            if value is not missing:
-                setattr(rv, key, value)
-
-        if cache_size is not missing:
-            rv.cache = create_cache(cache_size)
-        else:
-            rv.cache = copy_cache(self.cache)
-
-        rv.extensions = {}
-        for key, value in self.extensions.iteritems():
-            rv.extensions[key] = value.bind(rv)
-        if extensions is not missing:
-            rv.extensions.update(load_extensions(rv, extensions))
-
-        return _environment_sanity_check(rv)
-
-    lexer = property(get_lexer, doc="The lexer for this environment.")
-
-    def iter_extensions(self):
-        """Iterates over the extensions by priority."""
-        return iter(sorted(self.extensions.values(),
-                           key=lambda x: x.priority))
-
-    def getitem(self, obj, argument):
-        """Get an item or attribute of an object but prefer the item."""
-        try:
-            return obj[argument]
-        except (TypeError, LookupError):
-            if isinstance(argument, basestring):
-                try:
-                    attr = str(argument)
-                except:
-                    pass
-                else:
-                    try:
-                        return getattr(obj, attr)
-                    except AttributeError:
-                        pass
-            return self.undefined(obj=obj, name=argument)
-
-    def getattr(self, obj, attribute):
-        """Get an item or attribute of an object but prefer the attribute.
-        Unlike :meth:`getitem` the attribute *must* be a bytestring.
-        """
-        try:
-            return getattr(obj, attribute)
-        except AttributeError:
-            pass
-        try:
-            return obj[attribute]
-        except (TypeError, LookupError, AttributeError):
-            return self.undefined(obj=obj, name=attribute)
-
-    @internalcode
-    def parse(self, source, name=None, filename=None):
-        """Parse the sourcecode and return the abstract syntax tree.  This
-        tree of nodes is used by the compiler to convert the template into
-        executable source- or bytecode.  This is useful for debugging or to
-        extract information from templates.
-
-        If you are :ref:`developing Jinja2 extensions <writing-extensions>`
-        this gives you a good overview of the node tree generated.
-        """
-        try:
-            return self._parse(source, name, filename)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        self.handle_exception(exc_info, source_hint=source)
-
-    def _parse(self, source, name, filename):
-        """Internal parsing function used by `parse` and `compile`."""
-        return Parser(self, source, name, _encode_filename(filename)).parse()
-
-    def lex(self, source, name=None, filename=None):
-        """Lex the given sourcecode and return a generator that yields
-        tokens as tuples in the form ``(lineno, token_type, value)``.
-        This can be useful for :ref:`extension development <writing-extensions>`
-        and debugging templates.
-
-        This does not perform preprocessing.  If you want the preprocessing
-        of the extensions to be applied you have to filter source through
-        the :meth:`preprocess` method.
-        """
-        source = unicode(source)
-        try:
-            return self.lexer.tokeniter(source, name, filename)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        self.handle_exception(exc_info, source_hint=source)
-
-    def preprocess(self, source, name=None, filename=None):
-        """Preprocesses the source with all extensions.  This is automatically
-        called for all parsing and compiling methods but *not* for :meth:`lex`
-        because there you usually only want the actual source tokenized.
-        """
-        return reduce(lambda s, e: e.preprocess(s, name, filename),
-                      self.iter_extensions(), unicode(source))
-
-    def _tokenize(self, source, name, filename=None, state=None):
-        """Called by the parser to do the preprocessing and filtering
-        for all the extensions.  Returns a :class:`~ambari_jinja2.lexer.TokenStream`.
-        """
-        source = self.preprocess(source, name, filename)
-        stream = self.lexer.tokenize(source, name, filename, state)
-        for ext in self.iter_extensions():
-            stream = ext.filter_stream(stream)
-            if not isinstance(stream, TokenStream):
-                stream = TokenStream(stream, name, filename)
-        return stream
-
-    def _generate(self, source, name, filename, defer_init=False):
-        """Internal hook that can be overriden to hook a different generate
-        method in.
-
-        .. versionadded:: 2.5
-        """
-        return generate(source, self, name, filename, defer_init=defer_init)
-
-    def _compile(self, source, filename):
-        """Internal hook that can be overriden to hook a different compile
-        method in.
-
-        .. versionadded:: 2.5
-        """
-        return compile(source, filename, 'exec')
-
-    @internalcode
-    def compile(self, source, name=None, filename=None, raw=False,
-                defer_init=False):
-        """Compile a node or template source code.  The `name` parameter is
-        the load name of the template after it was joined using
-        :meth:`join_path` if necessary, not the filename on the file system.
-        the `filename` parameter is the estimated filename of the template on
-        the file system.  If the template came from a database or memory this
-        can be omitted.
-
-        The return value of this method is a python code object.  If the `raw`
-        parameter is `True` the return value will be a string with python
-        code equivalent to the bytecode returned otherwise.  This method is
-        mainly used internally.
-
-        `defer_init` is use internally to aid the module code generator.  This
-        causes the generated code to be able to import without the global
-        environment variable to be set.
-
-        .. versionadded:: 2.4
-           `defer_init` parameter added.
-        """
-        source_hint = None
-        try:
-            if isinstance(source, basestring):
-                source_hint = source
-                source = self._parse(source, name, filename)
-            if self.optimized:
-                source = optimize(source, self)
-            source = self._generate(source, name, filename,
-                                    defer_init=defer_init)
-            if raw:
-                return source
-            if filename is None:
-                filename = '<template>'
-            else:
-                filename = _encode_filename(filename)
-            return self._compile(source, filename)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        self.handle_exception(exc_info, source_hint=source)
-
-    def compile_expression(self, source, undefined_to_none=True):
-        """A handy helper method that returns a callable that accepts keyword
-        arguments that appear as variables in the expression.  If called it
-        returns the result of the expression.
-
-        This is useful if applications want to use the same rules as Jinja
-        in template "configuration files" or similar situations.
-
-        Example usage:
-
-        >>> env = Environment()
-        >>> expr = env.compile_expression('foo == 42')
-        >>> expr(foo=23)
-        False
-        >>> expr(foo=42)
-        True
-
-        Per default the return value is converted to `None` if the
-        expression returns an undefined value.  This can be changed
-        by setting `undefined_to_none` to `False`.
-
-        >>> env.compile_expression('var')() is None
-        True
-        >>> env.compile_expression('var', undefined_to_none=False)()
-        Undefined
-
-        .. versionadded:: 2.1
-        """
-        parser = Parser(self, source, state='variable')
-        exc_info = None
-        try:
-            expr = parser.parse_expression()
-            if not parser.stream.eos:
-                raise TemplateSyntaxError('chunk after expression',
-                                          parser.stream.current.lineno,
-                                          None, None)
-            expr.set_environment(self)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        if exc_info is not None:
-            self.handle_exception(exc_info, source_hint=source)
-        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
-        template = self.from_string(nodes.Template(body, lineno=1))
-        return TemplateExpression(template, undefined_to_none)
-
-    def compile_templates(self, target, extensions=None, filter_func=None,
-                          zip='deflated', log_function=None,
-                          ignore_errors=True, py_compile=False):
-        """Compiles all the templates the loader can find, compiles them
-        and stores them in `target`.  If `zip` is `None`, instead of in a
-        zipfile, the templates will be will be stored in a directory.
-        By default a deflate zip algorithm is used, to switch to
-        the stored algorithm, `zip` can be set to ``'stored'``.
-
-        `extensions` and `filter_func` are passed to :meth:`list_templates`.
-        Each template returned will be compiled to the target folder or
-        zipfile.
-
-        By default template compilation errors are ignored.  In case a
-        log function is provided, errors are logged.  If you want template
-        syntax errors to abort the compilation you can set `ignore_errors`
-        to `False` and you will get an exception on syntax errors.
-
-        If `py_compile` is set to `True` .pyc files will be written to the
-        target instead of standard .py files.
-
-        .. versionadded:: 2.4
-        """
-        from ambari_jinja2.loaders import ModuleLoader
-
-        if log_function is None:
-            log_function = lambda x: None
-
-        if py_compile:
-            import imp, struct, marshal
-            py_header = imp.get_magic() + \
-                u'\xff\xff\xff\xff'.encode('iso-8859-15')
-
-        def write_file(filename, data, mode):
-            if zip:
-                info = ZipInfo(filename)
-                info.external_attr = 0755 << 16L
-                zip_file.writestr(info, data)
-            else:
-                f = open(os.path.join(target, filename), mode)
-                try:
-                    f.write(data)
-                finally:
-                    f.close()
-
-        if zip is not None:
-            from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
-            zip_file = ZipFile(target, 'w', dict(deflated=ZIP_DEFLATED,
-                                                 stored=ZIP_STORED)[zip])
-            log_function('Compiling into Zip archive "%s"' % target)
-        else:
-            if not os.path.isdir(target):
-                os.makedirs(target)
-            log_function('Compiling into folder "%s"' % target)
-
-        try:
-            for name in self.list_templates(extensions, filter_func):
-                source, filename, _ = self.loader.get_source(self, name)
-                try:
-                    code = self.compile(source, name, filename, True, True)
-                except TemplateSyntaxError, e:
-                    if not ignore_errors:
-                        raise
-                    log_function('Could not compile "%s": %s' % (name, e))
-                    continue
-
-                filename = ModuleLoader.get_module_filename(name)
-
-                if py_compile:
-                    c = self._compile(code, _encode_filename(filename))
-                    write_file(filename + 'c', py_header +
-                               marshal.dumps(c), 'wb')
-                    log_function('Byte-compiled "%s" as %s' %
-                                 (name, filename + 'c'))
-                else:
-                    write_file(filename, code, 'w')
-                    log_function('Compiled "%s" as %s' % (name, filename))
-        finally:
-            if zip:
-                zip_file.close()
-
-        log_function('Finished compiling templates')
-
-    def list_templates(self, extensions=None, filter_func=None):
-        """Returns a list of templates for this environment.  This requires
-        that the loader supports the loader's
-        :meth:`~BaseLoader.list_templates` method.
-
-        If there are other files in the template folder besides the
-        actual templates, the returned list can be filtered.  There are two
-        ways: either `extensions` is set to a list of file extensions for
-        templates, or a `filter_func` can be provided which is a callable that
-        is passed a template name and should return `True` if it should end up
-        in the result list.
-
-        If the loader does not support that, a :exc:`TypeError` is raised.
-        """
-        x = self.loader.list_templates()
-        if extensions is not None:
-            if filter_func is not None:
-                raise TypeError('either extensions or filter_func '
-                                'can be passed, but not both')
-            filter_func = lambda x: '.' in x and \
-                                    x.rsplit('.', 1)[1] in extensions
-        if filter_func is not None:
-            x = filter(filter_func, x)
-        return x
-
-    def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
-        """Exception handling helper.  This is used internally to either raise
-        rewritten exceptions or return a rendered traceback for the template.
-        """
-        global _make_traceback
-        if exc_info is None:
-            exc_info = sys.exc_info()
-
-        # the debugging module is imported when it's used for the first time.
-        # we're doing a lot of stuff there and for applications that do not
-        # get any exceptions in template rendering there is no need to load
-        # all of that.
-        if _make_traceback is None:
-            from ambari_jinja2.debug import make_traceback as _make_traceback
-        traceback = _make_traceback(exc_info, source_hint)
-        if rendered and self.exception_formatter is not None:
-            return self.exception_formatter(traceback)
-        if self.exception_handler is not None:
-            self.exception_handler(traceback)
-        exc_type, exc_value, tb = traceback.standard_exc_info
-        raise exc_type, exc_value, tb
-
-    def join_path(self, template, parent):
-        """Join a template with the parent.  By default all the lookups are
-        relative to the loader root so this method returns the `template`
-        parameter unchanged, but if the paths should be relative to the
-        parent template, this function can be used to calculate the real
-        template name.
-
-        Subclasses may override this method and implement template path
-        joining here.
-        """
-        return template
-
-    @internalcode
-    def _load_template(self, name, globals):
-        if self.loader is None:
-            raise TypeError('no loader for this environment specified')
-        if self.cache is not None:
-            template = self.cache.get(name)
-            if template is not None and (not self.auto_reload or \
-                                         template.is_up_to_date):
-                return template
-        template = self.loader.load(self, name, globals)
-        if self.cache is not None:
-            self.cache[name] = template
-        return template
-
-    @internalcode
-    def get_template(self, name, parent=None, globals=None):
-        """Load a template from the loader.  If a loader is configured this
-        method ask the loader for the template and returns a :class:`Template`.
-        If the `parent` parameter is not `None`, :meth:`join_path` is called
-        to get the real template name before loading.
-
-        The `globals` parameter can be used to provide template wide globals.
-        These variables are available in the context at render time.
-
-        If the template does not exist a :exc:`TemplateNotFound` exception is
-        raised.
-
-        .. versionchanged:: 2.4
-           If `name` is a :class:`Template` object it is returned from the
-           function unchanged.
-        """
-        if isinstance(name, Template):
-            return name
-        if parent is not None:
-            name = self.join_path(name, parent)
-        return self._load_template(name, self.make_globals(globals))
-
-    @internalcode
-    def select_template(self, names, parent=None, globals=None):
-        """Works like :meth:`get_template` but tries a number of templates
-        before it fails.  If it cannot find any of the templates, it will
-        raise a :exc:`TemplatesNotFound` exception.
-
-        .. versionadded:: 2.3
-
-        .. versionchanged:: 2.4
-           If `names` contains a :class:`Template` object it is returned
-           from the function unchanged.
-        """
-        if not names:
-            raise TemplatesNotFound(message=u'Tried to select from an empty list '
-                                            u'of templates.')
-        globals = self.make_globals(globals)
-        for name in names:
-            if isinstance(name, Template):
-                return name
-            if parent is not None:
-                name = self.join_path(name, parent)
-            try:
-                return self._load_template(name, globals)
-            except TemplateNotFound:
-                pass
-        raise TemplatesNotFound(names)
-
-    @internalcode
-    def get_or_select_template(self, template_name_or_list,
-                               parent=None, globals=None):
-        """Does a typecheck and dispatches to :meth:`select_template`
-        if an iterable of template names is given, otherwise to
-        :meth:`get_template`.
-
-        .. versionadded:: 2.3
-        """
-        if isinstance(template_name_or_list, basestring):
-            return self.get_template(template_name_or_list, parent, globals)
-        elif isinstance(template_name_or_list, Template):
-            return template_name_or_list
-        return self.select_template(template_name_or_list, parent, globals)
-
-    def from_string(self, source, globals=None, template_class=None):
-        """Load a template from a string.  This parses the source given and
-        returns a :class:`Template` object.
-        """
-        globals = self.make_globals(globals)
-        cls = template_class or self.template_class
-        return cls.from_code(self, self.compile(source), globals, None)
-
-    def make_globals(self, d):
-        """Return a dict for the globals."""
-        if not d:
-            return self.globals
-        return dict(self.globals, **d)
-
-
-class Template(object):
-    """The central template object.  This class represents a compiled template
-    and is used to evaluate it.
-
-    Normally the template object is generated from an :class:`Environment` but
-    it also has a constructor that makes it possible to create a template
-    instance directly using the constructor.  It takes the same arguments as
-    the environment constructor but it's not possible to specify a loader.
-
-    Every template object has a few methods and members that are guaranteed
-    to exist.  However it's important that a template object should be
-    considered immutable.  Modifications on the object are not supported.
-
-    Template objects created from the constructor rather than an environment
-    do have an `environment` attribute that points to a temporary environment
-    that is probably shared with other templates created with the constructor
-    and compatible settings.
-
-    >>> template = Template('Hello {{ name }}!')
-    >>> template.render(name='John Doe')
-    u'Hello John Doe!'
-
-    >>> stream = template.stream(name='John Doe')
-    >>> stream.next()
-    u'Hello John Doe!'
-    >>> stream.next()
-    Traceback (most recent call last):
-        ...
-    StopIteration
-    """
-
-    def __new__(cls, source,
-                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,
-                line_statement_prefix=LINE_STATEMENT_PREFIX,
-                line_comment_prefix=LINE_COMMENT_PREFIX,
-                trim_blocks=TRIM_BLOCKS,
-                newline_sequence=NEWLINE_SEQUENCE,
-                extensions=(),
-                optimized=True,
-                undefined=Undefined,
-                finalize=None,
-                autoescape=False):
-        env = get_spontaneous_environment(
-            block_start_string, block_end_string, variable_start_string,
-            variable_end_string, comment_start_string, comment_end_string,
-            line_statement_prefix, line_comment_prefix, trim_blocks,
-            newline_sequence, frozenset(extensions), optimized, undefined,
-            finalize, autoescape, None, 0, False, None)
-        return env.from_string(source, template_class=cls)
-
-    @classmethod
-    def from_code(cls, environment, code, globals, uptodate=None):
-        """Creates a template object from compiled code and the globals.  This
-        is used by the loaders and environment to create a template object.
-        """
-        namespace = {
-            'environment':  environment,
-            '__file__':     code.co_filename
-        }
-        exec code in namespace
-        rv = cls._from_namespace(environment, namespace, globals)
-        rv._uptodate = uptodate
-        return rv
-
-    @classmethod
-    def from_module_dict(cls, environment, module_dict, globals):
-        """Creates a template object from a module.  This is used by the
-        module loader to create a template object.
-
-        .. versionadded:: 2.4
-        """
-        return cls._from_namespace(environment, module_dict, globals)
-
-    @classmethod
-    def _from_namespace(cls, environment, namespace, globals):
-        t = object.__new__(cls)
-        t.environment = environment
-        t.globals = globals
-        t.name = namespace['name']
-        t.filename = namespace['__file__']
-        t.blocks = namespace['blocks']
-
-        # render function and module
-        t.root_render_func = namespace['root']
-        t._module = None
-
-        # debug and loader helpers
-        t._debug_info = namespace['debug_info']
-        t._uptodate = None
-
-        # store the reference
-        namespace['environment'] = environment
-        namespace['__jinja_template__'] = t
-
-        return t
-
-    def render(self, *args, **kwargs):
-        """This method accepts the same arguments as the `dict` constructor:
-        A dict, a dict subclass or some keyword arguments.  If no arguments
-        are given the context will be empty.  These two calls do the same::
-
-            template.render(knights='that say nih')
-            template.render({'knights': 'that say nih'})
-
-        This will return the rendered template as unicode string.
-        """
-        vars = dict(*args, **kwargs)
-        try:
-            return concat(self.root_render_func(self.new_context(vars)))
-        except:
-            exc_info = sys.exc_info()
-        return self.environment.handle_exception(exc_info, True)
-
-    def stream(self, *args, **kwargs):
-        """Works exactly like :meth:`generate` but returns a
-        :class:`TemplateStream`.
-        """
-        return TemplateStream(self.generate(*args, **kwargs))
-
-    def generate(self, *args, **kwargs):
-        """For very large templates it can be useful to not render the whole
-        template at once but evaluate each statement after another and yield
-        piece for piece.  This method basically does exactly that and returns
-        a generator that yields one item after another as unicode strings.
-
-        It accepts the same arguments as :meth:`render`.
-        """
-        vars = dict(*args, **kwargs)
-        try:
-            for event in self.root_render_func(self.new_context(vars)):
-                yield event
-        except:
-            exc_info = sys.exc_info()
-        else:
-            return
-        yield self.environment.handle_exception(exc_info, True)
-
-    def new_context(self, vars=None, shared=False, locals=None):
-        """Create a new :class:`Context` for this template.  The vars
-        provided will be passed to the template.  Per default the globals
-        are added to the context.  If shared is set to `True` the data
-        is passed as it to the context without adding the globals.
-
-        `locals` can be a dict of local variables for internal usage.
-        """
-        return new_context(self.environment, self.name, self.blocks,
-                           vars, shared, self.globals, locals)
-
-    def make_module(self, vars=None, shared=False, locals=None):
-        """This method works like the :attr:`module` attribute when called
-        without arguments but it will evaluate the template on every call
-        rather than caching it.  It's also possible to provide
-        a dict which is then used as context.  The arguments are the same
-        as for the :meth:`new_context` method.
-        """
-        return TemplateModule(self, self.new_context(vars, shared, locals))
-
-    @property
-    def module(self):
-        """The template as module.  This is used for imports in the
-        template runtime but is also useful if one wants to access
-        exported template variables from the Python layer:
-
-        >>> t = Template('{% macro foo() %}42{% endmacro %}23')
-        >>> unicode(t.module)
-        u'23'
-        >>> t.module.foo()
-        u'42'
-        """
-        if self._module is not None:
-            return self._module
-        self._module = rv = self.make_module()
-        return rv
-
-    def get_corresponding_lineno(self, lineno):
-        """Return the source line number of a line number in the
-        generated bytecode as they are not in sync.
-        """
-        for template_line, code_line in reversed(self.debug_info):
-            if code_line <= lineno:
-                return template_line
-        return 1
-
-    @property
-    def is_up_to_date(self):
-        """If this variable is `False` there is a newer version available."""
-        if self._uptodate is None:
-            return True
-        return self._uptodate()
-
-    @property
-    def debug_info(self):
-        """The debug info mapping."""
-        return [tuple(map(int, x.split('='))) for x in
-                self._debug_info.split('&')]
-
-    def __repr__(self):
-        if self.name is None:
-            name = 'memory:%x' % id(self)
-        else:
-            name = repr(self.name)
-        return '<%s %s>' % (self.__class__.__name__, name)
-
-
-class TemplateModule(object):
-    """Represents an imported template.  All the exported names of the
-    template are available as attributes on this object.  Additionally
-    converting it into an unicode- or bytestrings renders the contents.
-    """
-
-    def __init__(self, template, context):
-        self._body_stream = list(template.root_render_func(context))
-        self.__dict__.update(context.get_exported())
-        self.__name__ = template.name
-
-    def __html__(self):
-        return Markup(concat(self._body_stream))
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        return concat(self._body_stream)
-
-    def __repr__(self):
-        if self.__name__ is None:
-            name = 'memory:%x' % id(self)
-        else:
-            name = repr(self.__name__)
-        return '<%s %s>' % (self.__class__.__name__, name)
-
-
-class TemplateExpression(object):
-    """The :meth:`ambari_jinja2.Environment.compile_expression` method returns an
-    instance of this object.  It encapsulates the expression-like access
-    to the template with an expression it wraps.
-    """
-
-    def __init__(self, template, undefined_to_none):
-        self._template = template
-        self._undefined_to_none = undefined_to_none
-
-    def __call__(self, *args, **kwargs):
-        context = self._template.new_context(dict(*args, **kwargs))
-        consume(self._template.root_render_func(context))
-        rv = context.vars['result']
-        if self._undefined_to_none and isinstance(rv, Undefined):
-            rv = None
-        return rv
-
-
-class TemplateStream(object):
-    """A template stream works pretty much like an ordinary python generator
-    but it can buffer multiple items to reduce the number of total iterations.
-    Per default the output is unbuffered which means that for every unbuffered
-    instruction in the template one unicode string is yielded.
-
-    If buffering is enabled with a buffer size of 5, five items are combined
-    into a new unicode string.  This is mainly useful if you are streaming
-    big templates to a client via WSGI which flushes after each iteration.
-    """
-
-    def __init__(self, gen):
-        self._gen = gen
-        self.disable_buffering()
-
-    def dump(self, fp, encoding=None, errors='strict'):
-        """Dump the complete stream into a file or file-like object.
-        Per default unicode strings are written, if you want to encode
-        before writing specifiy an `encoding`.
-
-        Example usage::
-
-            Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
-        """
-        close = False
-        if isinstance(fp, basestring):
-            fp = file(fp, 'w')
-            close = True
-        try:
-            if encoding is not None:
-                iterable = (x.encode(encoding, errors) for x in self)
-            else:
-                iterable = self
-            if hasattr(fp, 'writelines'):
-                fp.writelines(iterable)
-            else:
-                for item in iterable:
-                    fp.write(item)
-        finally:
-            if close:
-                fp.close()
-
-    def disable_buffering(self):
-        """Disable the output buffering."""
-        self._next = self._gen.next
-        self.buffered = False
-
-    def enable_buffering(self, size=5):
-        """Enable buffering.  Buffer `size` items before yielding them."""
-        if size <= 1:
-            raise ValueError('buffer size too small')
-
-        def generator(next):
-            buf = []
-            c_size = 0
-            push = buf.append
-
-            while 1:
-                try:
-                    while c_size < size:
-                        c = next()
-                        push(c)
-                        if c:
-                            c_size += 1
-                except StopIteration:
-                    if not c_size:
-                        return
-                yield concat(buf)
-                del buf[:]
-                c_size = 0
-
-        self.buffered = True
-        self._next = generator(self._gen.next).next
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        return self._next()
-
-
-# hook in default template class.  if anyone reads this comment: ignore that
-# it's possible to use custom templates ;-)
-Environment.template_class = Template

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py
deleted file mode 100644
index 346c706..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.exceptions
-    ~~~~~~~~~~~~~~~~~
-
-    Jinja exceptions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-class TemplateError(Exception):
-    """Baseclass for all template errors."""
-
-    def __init__(self, message=None):
-        if message is not None:
-            message = unicode(message).encode('utf-8')
-        Exception.__init__(self, message)
-
-    @property
-    def message(self):
-        if self.args:
-            message = self.args[0]
-            if message is not None:
-                return message.decode('utf-8', 'replace')
-
-
-class TemplateNotFound(IOError, LookupError, TemplateError):
-    """Raised if a template does not exist."""
-
-    # looks weird, but removes the warning descriptor that just
-    # bogusly warns us about message being deprecated
-    message = None
-
-    def __init__(self, name, message=None):
-        IOError.__init__(self)
-        if message is None:
-            message = name
-        self.message = message
-        self.name = name
-        self.templates = [name]
-
-    def __str__(self):
-        return self.message.encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        return self.message
-
-
-class TemplatesNotFound(TemplateNotFound):
-    """Like :class:`TemplateNotFound` but raised if multiple templates
-    are selected.  This is a subclass of :class:`TemplateNotFound`
-    exception, so just catching the base exception will catch both.
-
-    .. versionadded:: 2.2
-    """
-
-    def __init__(self, names=(), message=None):
-        if message is None:
-            message = u'non of the templates given were found: ' + \
-                      u', '.join(map(unicode, names))
-        TemplateNotFound.__init__(self, names and names[-1] or None, message)
-        self.templates = list(names)
-
-
-class TemplateSyntaxError(TemplateError):
-    """Raised to tell the user that there is a problem with the template."""
-
-    def __init__(self, message, lineno, name=None, filename=None):
-        TemplateError.__init__(self, message)
-        self.lineno = lineno
-        self.name = name
-        self.filename = filename
-        self.source = None
-
-        # this is set to True if the debug.translate_syntax_error
-        # function translated the syntax error into a new traceback
-        self.translated = False
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        # for translated errors we only return the message
-        if self.translated:
-            return self.message
-
-        # otherwise attach some stuff
-        location = 'line %d' % self.lineno
-        name = self.filename or self.name
-        if name:
-            location = 'File "%s", %s' % (name, location)
-        lines = [self.message, '  ' + location]
-
-        # if the source is set, add the line to the output
-        if self.source is not None:
-            try:
-                line = self.source.splitlines()[self.lineno - 1]
-            except IndexError:
-                line = None
-            if line:
-                lines.append('    ' + line.strip())
-
-        return u'\n'.join(lines)
-
-
-class TemplateAssertionError(TemplateSyntaxError):
-    """Like a template syntax error, but covers cases where something in the
-    template caused an error at compile time that wasn't necessarily caused
-    by a syntax error.  However it's a direct subclass of
-    :exc:`TemplateSyntaxError` and has the same attributes.
-    """
-
-
-class TemplateRuntimeError(TemplateError):
-    """A generic runtime error in the template engine.  Under some situations
-    Jinja may raise this exception.
-    """
-
-
-class UndefinedError(TemplateRuntimeError):
-    """Raised if a template tries to operate on :class:`Undefined`."""
-
-
-class SecurityError(TemplateRuntimeError):
-    """Raised if a template tries to do something insecure if the
-    sandbox is enabled.
-    """
-
-
-class FilterArgumentError(TemplateRuntimeError):
-    """This error is raised if a filter was called with inappropriate
-    arguments
-    """

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py
deleted file mode 100644
index 20149d1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py
+++ /dev/null
@@ -1,610 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.ext
-    ~~~~~~~~~~
-
-    Jinja extensions allow to add custom tags similar to the way django custom
-    tags work.  By default two example extensions exist: an i18n and a cache
-    extension.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from collections import deque
-from ambari_jinja2 import nodes
-from ambari_jinja2.defaults import *
-from ambari_jinja2.environment import Environment
-from ambari_jinja2.runtime import Undefined, concat
-from ambari_jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
-from ambari_jinja2.utils import contextfunction, import_string, Markup, next
-
-
-# the only real useful gettext functions for a Jinja template.  Note
-# that ugettext must be assigned to gettext as Jinja doesn't support
-# non unicode strings.
-GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext')
-
-
-class ExtensionRegistry(type):
-    """Gives the extension an unique identifier."""
-
-    def __new__(cls, name, bases, d):
-        rv = type.__new__(cls, name, bases, d)
-        rv.identifier = rv.__module__ + '.' + rv.__name__
-        return rv
-
-
-class Extension(object):
-    """Extensions can be used to add extra functionality to the Jinja template
-    system at the parser level.  Custom extensions are bound to an environment
-    but may not store environment specific data on `self`.  The reason for
-    this is that an extension can be bound to another environment (for
-    overlays) by creating a copy and reassigning the `environment` attribute.
-
-    As extensions are created by the environment they cannot accept any
-    arguments for configuration.  One may want to work around that by using
-    a factory function, but that is not possible as extensions are identified
-    by their import name.  The correct way to configure the extension is
-    storing the configuration values on the environment.  Because this way the
-    environment ends up acting as central configuration storage the
-    attributes may clash which is why extensions have to ensure that the names
-    they choose for configuration are not too generic.  ``prefix`` for example
-    is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
-    name as includes the name of the extension (fragment cache).
-    """
-    __metaclass__ = ExtensionRegistry
-
-    #: if this extension parses this is the list of tags it's listening to.
-    tags = set()
-
-    #: the priority of that extension.  This is especially useful for
-    #: extensions that preprocess values.  A lower value means higher
-    #: priority.
-    #:
-    #: .. versionadded:: 2.4
-    priority = 100
-
-    def __init__(self, environment):
-        self.environment = environment
-
-    def bind(self, environment):
-        """Create a copy of this extension bound to another environment."""
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.environment = environment
-        return rv
-
-    def preprocess(self, source, name, filename=None):
-        """This method is called before the actual lexing and can be used to
-        preprocess the source.  The `filename` is optional.  The return value
-        must be the preprocessed source.
-        """
-        return source
-
-    def filter_stream(self, stream):
-        """It's passed a :class:`~ambari_jinja2.lexer.TokenStream` that can be used
-        to filter tokens returned.  This method has to return an iterable of
-        :class:`~ambari_jinja2.lexer.Token`\s, but it doesn't have to return a
-        :class:`~ambari_jinja2.lexer.TokenStream`.
-
-        In the `ext` folder of the Jinja2 source distribution there is a file
-        called `inlinegettext.py` which implements a filter that utilizes this
-        method.
-        """
-        return stream
-
-    def parse(self, parser):
-        """If any of the :attr:`tags` matched this method is called with the
-        parser as first argument.  The token the parser stream is pointing at
-        is the name token that matched.  This method has to return one or a
-        list of multiple nodes.
-        """
-        raise NotImplementedError()
-
-    def attr(self, name, lineno=None):
-        """Return an attribute node for the current extension.  This is useful
-        to pass constants on extensions to generated template code::
-
-            self.attr('_my_attribute', lineno=lineno)
-        """
-        return nodes.ExtensionAttribute(self.identifier, name, lineno=lineno)
-
-    def call_method(self, name, args=None, kwargs=None, dyn_args=None,
-                    dyn_kwargs=None, lineno=None):
-        """Call a method of the extension.  This is a shortcut for
-        :meth:`attr` + :class:`ambari_jinja2.nodes.Call`.
-        """
-        if args is None:
-            args = []
-        if kwargs is None:
-            kwargs = []
-        return nodes.Call(self.attr(name, lineno=lineno), args, kwargs,
-                          dyn_args, dyn_kwargs, lineno=lineno)
-
-
-@contextfunction
-def _gettext_alias(__context, *args, **kwargs):
-    return __context.call(__context.resolve('gettext'), *args, **kwargs)
-
-
-def _make_new_gettext(func):
-    @contextfunction
-    def gettext(__context, __string, **variables):
-        rv = __context.call(func, __string)
-        if __context.eval_ctx.autoescape:
-            rv = Markup(rv)
-        return rv % variables
-    return gettext
-
-
-def _make_new_ngettext(func):
-    @contextfunction
-    def ngettext(__context, __singular, __plural, __num, **variables):
-        variables.setdefault('num', __num)
-        rv = __context.call(func, __singular, __plural, __num)
-        if __context.eval_ctx.autoescape:
-            rv = Markup(rv)
-        return rv % variables
-    return ngettext
-
-
-class InternationalizationExtension(Extension):
-    """This extension adds gettext support to Jinja2."""
-    tags = set(['trans'])
-
-    # TODO: the i18n extension is currently reevaluating values in a few
-    # situations.  Take this example:
-    #   {% trans count=something() %}{{ count }} foo{% pluralize
-    #     %}{{ count }} fooss{% endtrans %}
-    # something is called twice here.  One time for the gettext value and
-    # the other time for the n-parameter of the ngettext function.
-
-    def __init__(self, environment):
-        Extension.__init__(self, environment)
-        environment.globals['_'] = _gettext_alias
-        environment.extend(
-            install_gettext_translations=self._install,
-            install_null_translations=self._install_null,
-            install_gettext_callables=self._install_callables,
-            uninstall_gettext_translations=self._uninstall,
-            extract_translations=self._extract,
-            newstyle_gettext=False
-        )
-
-    def _install(self, translations, newstyle=None):
-        gettext = getattr(translations, 'ugettext', None)
-        if gettext is None:
-            gettext = translations.gettext
-        ngettext = getattr(translations, 'ungettext', None)
-        if ngettext is None:
-            ngettext = translations.ngettext
-        self._install_callables(gettext, ngettext, newstyle)
-
-    def _install_null(self, newstyle=None):
-        self._install_callables(
-            lambda x: x,
-            lambda s, p, n: (n != 1 and (p,) or (s,))[0],
-            newstyle
-        )
-
-    def _install_callables(self, gettext, ngettext, newstyle=None):
-        if newstyle is not None:
-            self.environment.newstyle_gettext = newstyle
-        if self.environment.newstyle_gettext:
-            gettext = _make_new_gettext(gettext)
-            ngettext = _make_new_ngettext(ngettext)
-        self.environment.globals.update(
-            gettext=gettext,
-            ngettext=ngettext
-        )
-
-    def _uninstall(self, translations):
-        for key in 'gettext', 'ngettext':
-            self.environment.globals.pop(key, None)
-
-    def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
-        if isinstance(source, basestring):
-            source = self.environment.parse(source)
-        return extract_from_ast(source, gettext_functions)
-
-    def parse(self, parser):
-        """Parse a translatable tag."""
-        lineno = next(parser.stream).lineno
-        num_called_num = False
-
-        # find all the variables referenced.  Additionally a variable can be
-        # defined in the body of the trans block too, but this is checked at
-        # a later state.
-        plural_expr = None
-        variables = {}
-        while parser.stream.current.type != 'block_end':
-            if variables:
-                parser.stream.expect('comma')
-
-            # skip colon for python compatibility
-            if parser.stream.skip_if('colon'):
-                break
-
-            name = parser.stream.expect('name')
-            if name.value in variables:
-                parser.fail('translatable variable %r defined twice.' %
-                            name.value, name.lineno,
-                            exc=TemplateAssertionError)
-
-            # expressions
-            if parser.stream.current.type == 'assign':
-                next(parser.stream)
-                variables[name.value] = var = parser.parse_expression()
-            else:
-                variables[name.value] = var = nodes.Name(name.value, 'load')
-
-            if plural_expr is None:
-                plural_expr = var
-                num_called_num = name.value == 'num'
-
-        parser.stream.expect('block_end')
-
-        plural = plural_names = None
-        have_plural = False
-        referenced = set()
-
-        # now parse until endtrans or pluralize
-        singular_names, singular = self._parse_block(parser, True)
-        if singular_names:
-            referenced.update(singular_names)
-            if plural_expr is None:
-                plural_expr = nodes.Name(singular_names[0], 'load')
-                num_called_num = singular_names[0] == 'num'
-
-        # if we have a pluralize block, we parse that too
-        if parser.stream.current.test('name:pluralize'):
-            have_plural = True
-            next(parser.stream)
-            if parser.stream.current.type != 'block_end':
-                name = parser.stream.expect('name')
-                if name.value not in variables:
-                    parser.fail('unknown variable %r for pluralization' %
-                                name.value, name.lineno,
-                                exc=TemplateAssertionError)
-                plural_expr = variables[name.value]
-                num_called_num = name.value == 'num'
-            parser.stream.expect('block_end')
-            plural_names, plural = self._parse_block(parser, False)
-            next(parser.stream)
-            referenced.update(plural_names)
-        else:
-            next(parser.stream)
-
-        # register free names as simple name expressions
-        for var in referenced:
-            if var not in variables:
-                variables[var] = nodes.Name(var, 'load')
-
-        if not have_plural:
-            plural_expr = None
-        elif plural_expr is None:
-            parser.fail('pluralize without variables', lineno)
-
-        node = self._make_node(singular, plural, variables, plural_expr,
-                               bool(referenced),
-                               num_called_num and have_plural)
-        node.set_lineno(lineno)
-        return node
-
-    def _parse_block(self, parser, allow_pluralize):
-        """Parse until the next block tag with a given name."""
-        referenced = []
-        buf = []
-        while 1:
-            if parser.stream.current.type == 'data':
-                buf.append(parser.stream.current.value.replace('%', '%%'))
-                next(parser.stream)
-            elif parser.stream.current.type == 'variable_begin':
-                next(parser.stream)
-                name = parser.stream.expect('name').value
-                referenced.append(name)
-                buf.append('%%(%s)s' % name)
-                parser.stream.expect('variable_end')
-            elif parser.stream.current.type == 'block_begin':
-                next(parser.stream)
-                if parser.stream.current.test('name:endtrans'):
-                    break
-                elif parser.stream.current.test('name:pluralize'):
-                    if allow_pluralize:
-                        break
-                    parser.fail('a translatable section can have only one '
-                                'pluralize section')
-                parser.fail('control structures in translatable sections are '
-                            'not allowed')
-            elif parser.stream.eos:
-                parser.fail('unclosed translation block')
-            else:
-                assert False, 'internal parser error'
-
-        return referenced, concat(buf)
-
-    def _make_node(self, singular, plural, variables, plural_expr,
-                   vars_referenced, num_called_num):
-        """Generates a useful node from the data provided."""
-        # no variables referenced?  no need to escape for old style
-        # gettext invocations only if there are vars.
-        if not vars_referenced and not self.environment.newstyle_gettext:
-            singular = singular.replace('%%', '%')
-            if plural:
-                plural = plural.replace('%%', '%')
-
-        # singular only:
-        if plural_expr is None:
-            gettext = nodes.Name('gettext', 'load')
-            node = nodes.Call(gettext, [nodes.Const(singular)],
-                              [], None, None)
-
-        # singular and plural
-        else:
-            ngettext = nodes.Name('ngettext', 'load')
-            node = nodes.Call(ngettext, [
-                nodes.Const(singular),
-                nodes.Const(plural),
-                plural_expr
-            ], [], None, None)
-
-        # in case newstyle gettext is used, the method is powerful
-        # enough to handle the variable expansion and autoescape
-        # handling itself
-        if self.environment.newstyle_gettext:
-            for key, value in variables.iteritems():
-                # the function adds that later anyways in case num was
-                # called num, so just skip it.
-                if num_called_num and key == 'num':
-                    continue
-                node.kwargs.append(nodes.Keyword(key, value))
-
-        # otherwise do that here
-        else:
-            # mark the return value as safe if we are in an
-            # environment with autoescaping turned on
-            node = nodes.MarkSafeIfAutoescape(node)
-            if variables:
-                node = nodes.Mod(node, nodes.Dict([
-                    nodes.Pair(nodes.Const(key), value)
-                    for key, value in variables.items()
-                ]))
-        return nodes.Output([node])
-
-
-class ExprStmtExtension(Extension):
-    """Adds a `do` tag to Jinja2 that works like the print statement just
-    that it doesn't print the return value.
-    """
-    tags = set(['do'])
-
-    def parse(self, parser):
-        node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
-        node.node = parser.parse_tuple()
-        return node
-
-
-class LoopControlExtension(Extension):
-    """Adds break and continue to the template engine."""
-    tags = set(['break', 'continue'])
-
-    def parse(self, parser):
-        token = next(parser.stream)
-        if token.value == 'break':
-            return nodes.Break(lineno=token.lineno)
-        return nodes.Continue(lineno=token.lineno)
-
-
-class WithExtension(Extension):
-    """Adds support for a django-like with block."""
-    tags = set(['with'])
-
-    def parse(self, parser):
-        node = nodes.Scope(lineno=next(parser.stream).lineno)
-        assignments = []
-        while parser.stream.current.type != 'block_end':
-            lineno = parser.stream.current.lineno
-            if assignments:
-                parser.stream.expect('comma')
-            target = parser.parse_assign_target()
-            parser.stream.expect('assign')
-            expr = parser.parse_expression()
-            assignments.append(nodes.Assign(target, expr, lineno=lineno))
-        node.body = assignments + \
-            list(parser.parse_statements(('name:endwith',),
-                                         drop_needle=True))
-        return node
-
-
-class AutoEscapeExtension(Extension):
-    """Changes auto escape rules for a scope."""
-    tags = set(['autoescape'])
-
-    def parse(self, parser):
-        node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
-        node.options = [
-            nodes.Keyword('autoescape', parser.parse_expression())
-        ]
-        node.body = parser.parse_statements(('name:endautoescape',),
-                                            drop_needle=True)
-        return nodes.Scope([node])
-
-
-def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
-                     babel_style=True):
-    """Extract localizable strings from the given template node.  Per
-    default this function returns matches in babel style that means non string
-    parameters as well as keyword arguments are returned as `None`.  This
-    allows Babel to figure out what you really meant if you are using
-    gettext functions that allow keyword arguments for placeholder expansion.
-    If you don't want that behavior set the `babel_style` parameter to `False`
-    which causes only strings to be returned and parameters are always stored
-    in tuples.  As a consequence invalid gettext calls (calls without a single
-    string parameter or string parameters after non-string parameters) are
-    skipped.
-
-    This example explains the behavior:
-
-    >>> from ambari_jinja2 import Environment
-    >>> env = Environment()
-    >>> node = env.parse('{{ (_("foo"), _(), ngettext("foo", "bar", 42)) }}')
-    >>> list(extract_from_ast(node))
-    [(1, '_', 'foo'), (1, '_', ()), (1, 'ngettext', ('foo', 'bar', None))]
-    >>> list(extract_from_ast(node, babel_style=False))
-    [(1, '_', ('foo',)), (1, 'ngettext', ('foo', 'bar'))]
-
-    For every string found this function yields a ``(lineno, function,
-    message)`` tuple, where:
-
-    * ``lineno`` is the number of the line on which the string was found,
-    * ``function`` is the name of the ``gettext`` function used (if the
-      string was extracted from embedded Python code), and
-    *  ``message`` is the string itself (a ``unicode`` object, or a tuple
-       of ``unicode`` objects for functions with multiple string arguments).
-
-    This extraction function operates on the AST and is because of that unable
-    to extract any comments.  For comment support you have to use the babel
-    extraction interface or extract comments yourself.
-    """
-    for node in node.find_all(nodes.Call):
-        if not isinstance(node.node, nodes.Name) or \
-           node.node.name not in gettext_functions:
-            continue
-
-        strings = []
-        for arg in node.args:
-            if isinstance(arg, nodes.Const) and \
-               isinstance(arg.value, basestring):
-                strings.append(arg.value)
-            else:
-                strings.append(None)
-
-        for arg in node.kwargs:
-            strings.append(None)
-        if node.dyn_args is not None:
-            strings.append(None)
-        if node.dyn_kwargs is not None:
-            strings.append(None)
-
-        if not babel_style:
-            strings = tuple(x for x in strings if x is not None)
-            if not strings:
-                continue
-        else:
-            if len(strings) == 1:
-                strings = strings[0]
-            else:
-                strings = tuple(strings)
-        yield node.lineno, node.node.name, strings
-
-
-class _CommentFinder(object):
-    """Helper class to find comments in a token stream.  Can only
-    find comments for gettext calls forwards.  Once the comment
-    from line 4 is found, a comment for line 1 will not return a
-    usable value.
-    """
-
-    def __init__(self, tokens, comment_tags):
-        self.tokens = tokens
-        self.comment_tags = comment_tags
-        self.offset = 0
-        self.last_lineno = 0
-
-    def find_backwards(self, offset):
-        try:
-            for _, token_type, token_value in \
-                    reversed(self.tokens[self.offset:offset]):
-                if token_type in ('comment', 'linecomment'):
-                    try:
-                        prefix, comment = token_value.split(None, 1)
-                    except ValueError:
-                        continue
-                    if prefix in self.comment_tags:
-                        return [comment.rstrip()]
-            return []
-        finally:
-            self.offset = offset
-
-    def find_comments(self, lineno):
-        if not self.comment_tags or self.last_lineno > lineno:
-            return []
-        for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset:]):
-            if token_lineno > lineno:
-                return self.find_backwards(self.offset + idx)
-        return self.find_backwards(len(self.tokens))
-
-
-def babel_extract(fileobj, keywords, comment_tags, options):
-    """Babel extraction method for Jinja templates.
-
-    .. versionchanged:: 2.3
-       Basic support for translation comments was added.  If `comment_tags`
-       is now set to a list of keywords for extraction, the extractor will
-       try to find the best preceeding comment that begins with one of the
-       keywords.  For best results, make sure to not have more than one
-       gettext call in one line of code and the matching comment in the
-       same line or the line before.
-
-    .. versionchanged:: 2.5.1
-       The `newstyle_gettext` flag can be set to `True` to enable newstyle
-       gettext calls.
-
-    :param fileobj: the file-like object the messages should be extracted from
-    :param keywords: a list of keywords (i.e. function names) that should be
-                     recognized as translation functions
-    :param comment_tags: a list of translator tags to search for and include
-                         in the results.
-    :param options: a dictionary of additional options (optional)
-    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
-             (comments will be empty currently)
-    """
-    extensions = set()
-    for extension in options.get('extensions', '').split(','):
-        extension = extension.strip()
-        if not extension:
-            continue
-        extensions.add(import_string(extension))
-    if InternationalizationExtension not in extensions:
-        extensions.add(InternationalizationExtension)
-
-    def getbool(options, key, default=False):
-        options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true')
-
-    environment = Environment(
-        options.get('block_start_string', BLOCK_START_STRING),
-        options.get('block_end_string', BLOCK_END_STRING),
-        options.get('variable_start_string', VARIABLE_START_STRING),
-        options.get('variable_end_string', VARIABLE_END_STRING),
-        options.get('comment_start_string', COMMENT_START_STRING),
-        options.get('comment_end_string', COMMENT_END_STRING),
-        options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
-        options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
-        getbool(options, 'trim_blocks', TRIM_BLOCKS),
-        NEWLINE_SEQUENCE, frozenset(extensions),
-        cache_size=0,
-        auto_reload=False
-    )
-
-    if getbool(options, 'newstyle_gettext'):
-        environment.newstyle_gettext = True
-
-    source = fileobj.read().decode(options.get('encoding', 'utf-8'))
-    try:
-        node = environment.parse(source)
-        tokens = list(environment.lex(environment.preprocess(source)))
-    except TemplateSyntaxError, e:
-        # skip templates with syntax errors
-        return
-
-    finder = _CommentFinder(tokens, comment_tags)
-    for lineno, func, message in extract_from_ast(node, keywords):
-        yield lineno, func, message, finder.find_comments(lineno)
-
-
-#: nicer import names
-i18n = InternationalizationExtension
-do = ExprStmtExtension
-loopcontrols = LoopControlExtension
-with_ = WithExtension
-autoescape = AutoEscapeExtension


[22/59] [abbrv] git commit: Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

This reverts commit 7c3ea59fc05db44f9f8a3aebc3e370918fa53e60.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/570de228
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/570de228
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/570de228

Branch: refs/heads/branch-alerts-dev
Commit: 570de22829e9cbdf481215a4ba9207486cd81dc4
Parents: 5c0ef4f
Author: Mahadev Konar <ma...@apache.org>
Authored: Wed Sep 3 12:34:31 2014 -0700
Committer: Mahadev Konar <ma...@apache.org>
Committed: Wed Sep 3 12:34:31 2014 -0700

----------------------------------------------------------------------
 ambari-agent/pom.xml                            |   12 +-
 .../resource_management/TestContentSources.py   |    2 +-
 .../src/main/python/ambari_jinja2/AUTHORS       |   31 -
 .../src/main/python/ambari_jinja2/CHANGES       |  235 ---
 .../src/main/python/ambari_jinja2/LICENSE       |   31 -
 .../src/main/python/ambari_jinja2/MANIFEST.in   |   12 -
 .../src/main/python/ambari_jinja2/Makefile      |    4 -
 .../ambari_jinja2/ambari_jinja2/__init__.py     |   73 -
 .../ambari_jinja2/ambari_jinja2/_debugsupport.c |   78 -
 .../ambari_jinja2/_markupsafe/__init__.py       |  225 ---
 .../ambari_jinja2/_markupsafe/_bundle.py        |   49 -
 .../ambari_jinja2/_markupsafe/_constants.py     |  267 ---
 .../ambari_jinja2/_markupsafe/_native.py        |   45 -
 .../ambari_jinja2/_markupsafe/tests.py          |   80 -
 .../ambari_jinja2/ambari_jinja2/_stringdefs.py  |  130 --
 .../ambari_jinja2/ambari_jinja2/bccache.py      |  280 ---
 .../ambari_jinja2/ambari_jinja2/compiler.py     | 1640 ------------------
 .../ambari_jinja2/ambari_jinja2/constants.py    |   32 -
 .../python/ambari_jinja2/ambari_jinja2/debug.py |  308 ----
 .../ambari_jinja2/ambari_jinja2/defaults.py     |   40 -
 .../ambari_jinja2/ambari_jinja2/environment.py  | 1118 ------------
 .../ambari_jinja2/ambari_jinja2/exceptions.py   |  143 --
 .../python/ambari_jinja2/ambari_jinja2/ext.py   |  610 -------
 .../ambari_jinja2/ambari_jinja2/filters.py      |  719 --------
 .../python/ambari_jinja2/ambari_jinja2/lexer.py |  681 --------
 .../ambari_jinja2/ambari_jinja2/loaders.py      |  449 -----
 .../python/ambari_jinja2/ambari_jinja2/meta.py  |  102 --
 .../python/ambari_jinja2/ambari_jinja2/nodes.py |  901 ----------
 .../ambari_jinja2/ambari_jinja2/optimizer.py    |   68 -
 .../ambari_jinja2/ambari_jinja2/parser.py       |  896 ----------
 .../ambari_jinja2/ambari_jinja2/runtime.py      |  544 ------
 .../ambari_jinja2/ambari_jinja2/sandbox.py      |  271 ---
 .../python/ambari_jinja2/ambari_jinja2/tests.py |  146 --
 .../ambari_jinja2/testsuite/__init__.py         |   95 -
 .../ambari_jinja2/testsuite/api.py              |  240 ---
 .../ambari_jinja2/testsuite/core_tags.py        |  286 ---
 .../ambari_jinja2/testsuite/debug.py            |   60 -
 .../ambari_jinja2/testsuite/doctests.py         |   29 -
 .../ambari_jinja2/testsuite/ext.py              |  455 -----
 .../ambari_jinja2/testsuite/filters.py          |  291 ----
 .../ambari_jinja2/testsuite/imports.py          |  144 --
 .../ambari_jinja2/testsuite/inheritance.py      |  208 ---
 .../ambari_jinja2/testsuite/lexnparse.py        |  390 -----
 .../ambari_jinja2/testsuite/loader.py           |  191 --
 .../ambari_jinja2/testsuite/regression.py       |  258 ---
 .../testsuite/res/templates/broken.html         |    3 -
 .../testsuite/res/templates/foo/test.html       |    1 -
 .../testsuite/res/templates/syntaxerror.html    |    4 -
 .../testsuite/res/templates/test.html           |    1 -
 .../ambari_jinja2/testsuite/security.py         |  134 --
 .../ambari_jinja2/testsuite/tests.py            |   87 -
 .../ambari_jinja2/testsuite/utils.py            |   85 -
 .../python/ambari_jinja2/ambari_jinja2/utils.py |  601 -------
 .../ambari_jinja2/ambari_jinja2/visitor.py      |   87 -
 .../python/ambari_jinja2/artwork/jinjalogo.svg  |  132 --
 .../custom_fixers/fix_alt_unicode.py            |   13 -
 .../custom_fixers/fix_broken_reraising.py       |   21 -
 .../ambari_jinja2/custom_fixers/fix_xrange2.py  |   11 -
 .../src/main/python/ambari_jinja2/docs/Makefile |   75 -
 .../python/ambari_jinja2/docs/_static/jinja.js  |   26 -
 .../python/ambari_jinja2/docs/_static/print.css |    5 -
 .../python/ambari_jinja2/docs/_static/style.css |  390 -----
 .../ambari_jinja2/docs/_templates/genindex.html |   36 -
 .../ambari_jinja2/docs/_templates/layout.html   |   77 -
 .../docs/_templates/opensearch.xml              |    9 -
 .../ambari_jinja2/docs/_templates/page.html     |    4 -
 .../ambari_jinja2/docs/_templates/search.html   |   35 -
 .../src/main/python/ambari_jinja2/docs/api.rst  |  787 ---------
 .../ambari_jinja2/docs/cache_extension.py       |   56 -
 .../python/ambari_jinja2/docs/changelog.rst     |    3 -
 .../src/main/python/ambari_jinja2/docs/conf.py  |  141 --
 .../python/ambari_jinja2/docs/extensions.rst    |  347 ----
 .../src/main/python/ambari_jinja2/docs/faq.rst  |  191 --
 .../main/python/ambari_jinja2/docs/index.rst    |   27 -
 .../python/ambari_jinja2/docs/integration.rst   |   88 -
 .../main/python/ambari_jinja2/docs/intro.rst    |  168 --
 .../main/python/ambari_jinja2/docs/jinjaext.py  |  192 --
 .../main/python/ambari_jinja2/docs/sandbox.rst  |   46 -
 .../python/ambari_jinja2/docs/switching.rst     |  242 ---
 .../python/ambari_jinja2/docs/templates.rst     | 1365 ---------------
 .../main/python/ambari_jinja2/docs/tricks.rst   |  100 --
 .../ambari_jinja2/examples/basic/cycle.py       |   13 -
 .../ambari_jinja2/examples/basic/debugger.py    |    7 -
 .../ambari_jinja2/examples/basic/inheritance.py |   12 -
 .../examples/basic/templates/broken.html        |    6 -
 .../examples/basic/templates/subbroken.html     |    3 -
 .../python/ambari_jinja2/examples/basic/test.py |   27 -
 .../basic/test_filter_and_linestatements.py     |   25 -
 .../examples/basic/test_loop_filter.py          |   12 -
 .../ambari_jinja2/examples/basic/translate.py   |    6 -
 .../main/python/ambari_jinja2/examples/bench.py |  433 -----
 .../python/ambari_jinja2/examples/profile.py    |   52 -
 .../examples/rwbench/django/_form.html          |    1 -
 .../examples/rwbench/django/_input_field.html   |    1 -
 .../examples/rwbench/django/_textarea.html      |    1 -
 .../examples/rwbench/django/index.html          |   29 -
 .../examples/rwbench/django/layout.html         |   29 -
 .../ambari_jinja2/examples/rwbench/djangoext.py |  135 --
 .../examples/rwbench/genshi/helpers.html        |   12 -
 .../examples/rwbench/genshi/index.html          |   41 -
 .../examples/rwbench/genshi/layout.html         |   30 -
 .../examples/rwbench/jinja/helpers.html         |   12 -
 .../examples/rwbench/jinja/index.html           |   29 -
 .../examples/rwbench/jinja/layout.html          |   29 -
 .../examples/rwbench/mako/helpers.html          |   11 -
 .../examples/rwbench/mako/index.html            |   31 -
 .../examples/rwbench/mako/layout.html           |   30 -
 .../ambari_jinja2/examples/rwbench/rwbench.py   |  112 --
 .../python/ambari_jinja2/ext/Vim/htmljinja.vim  |   27 -
 .../main/python/ambari_jinja2/ext/Vim/jinja.vim |  113 --
 .../ext/django2jinja/django2jinja.py            |  768 --------
 .../ambari_jinja2/ext/django2jinja/example.py   |    7 -
 .../ext/django2jinja/templates/index.html       |   58 -
 .../ext/django2jinja/templates/layout.html      |    4 -
 .../ext/django2jinja/templates/subtemplate.html |    1 -
 .../python/ambari_jinja2/ext/djangojinja2.py    |   86 -
 .../python/ambari_jinja2/ext/inlinegettext.py   |   78 -
 .../src/main/python/ambari_jinja2/ext/jinja.el  |  213 ---
 .../main/python/ambari_jinja2/jinja2-debug.py   |   40 -
 .../main/python/ambari_jinja2/scripts/pylintrc  |  301 ----
 .../src/main/python/ambari_jinja2/setup.cfg     |    6 -
 .../src/main/python/ambari_jinja2/setup.py      |  110 --
 ambari-common/src/main/python/jinja2/AUTHORS    |   31 +
 ambari-common/src/main/python/jinja2/CHANGES    |  235 +++
 ambari-common/src/main/python/jinja2/LICENSE    |   31 +
 .../src/main/python/jinja2/MANIFEST.in          |   12 +
 ambari-common/src/main/python/jinja2/Makefile   |    4 +
 .../main/python/jinja2/artwork/jinjalogo.svg    |  132 ++
 .../jinja2/custom_fixers/fix_alt_unicode.py     |   13 +
 .../custom_fixers/fix_broken_reraising.py       |   21 +
 .../python/jinja2/custom_fixers/fix_xrange2.py  |   11 +
 .../src/main/python/jinja2/docs/Makefile        |   75 +
 .../main/python/jinja2/docs/_static/jinja.js    |   26 +
 .../main/python/jinja2/docs/_static/print.css   |    5 +
 .../main/python/jinja2/docs/_static/style.css   |  390 +++++
 .../python/jinja2/docs/_templates/genindex.html |   36 +
 .../python/jinja2/docs/_templates/layout.html   |   77 +
 .../jinja2/docs/_templates/opensearch.xml       |    9 +
 .../python/jinja2/docs/_templates/page.html     |    4 +
 .../python/jinja2/docs/_templates/search.html   |   35 +
 .../src/main/python/jinja2/docs/api.rst         |  787 +++++++++
 .../main/python/jinja2/docs/cache_extension.py  |   56 +
 .../src/main/python/jinja2/docs/changelog.rst   |    3 +
 .../src/main/python/jinja2/docs/conf.py         |  141 ++
 .../src/main/python/jinja2/docs/extensions.rst  |  347 ++++
 .../src/main/python/jinja2/docs/faq.rst         |  191 ++
 .../src/main/python/jinja2/docs/index.rst       |   27 +
 .../src/main/python/jinja2/docs/integration.rst |   88 +
 .../src/main/python/jinja2/docs/intro.rst       |  168 ++
 .../src/main/python/jinja2/docs/jinjaext.py     |  192 ++
 .../src/main/python/jinja2/docs/sandbox.rst     |   46 +
 .../src/main/python/jinja2/docs/switching.rst   |  242 +++
 .../src/main/python/jinja2/docs/templates.rst   | 1365 +++++++++++++++
 .../src/main/python/jinja2/docs/tricks.rst      |  100 ++
 .../main/python/jinja2/examples/basic/cycle.py  |   13 +
 .../python/jinja2/examples/basic/debugger.py    |    7 +
 .../python/jinja2/examples/basic/inheritance.py |   12 +
 .../jinja2/examples/basic/templates/broken.html |    6 +
 .../examples/basic/templates/subbroken.html     |    3 +
 .../main/python/jinja2/examples/basic/test.py   |   27 +
 .../basic/test_filter_and_linestatements.py     |   25 +
 .../jinja2/examples/basic/test_loop_filter.py   |   12 +
 .../python/jinja2/examples/basic/translate.py   |    6 +
 .../src/main/python/jinja2/examples/bench.py    |  433 +++++
 .../src/main/python/jinja2/examples/profile.py  |   52 +
 .../jinja2/examples/rwbench/django/_form.html   |    1 +
 .../examples/rwbench/django/_input_field.html   |    1 +
 .../examples/rwbench/django/_textarea.html      |    1 +
 .../jinja2/examples/rwbench/django/index.html   |   29 +
 .../jinja2/examples/rwbench/django/layout.html  |   29 +
 .../python/jinja2/examples/rwbench/djangoext.py |  135 ++
 .../jinja2/examples/rwbench/genshi/helpers.html |   12 +
 .../jinja2/examples/rwbench/genshi/index.html   |   41 +
 .../jinja2/examples/rwbench/genshi/layout.html  |   30 +
 .../jinja2/examples/rwbench/jinja/helpers.html  |   12 +
 .../jinja2/examples/rwbench/jinja/index.html    |   29 +
 .../jinja2/examples/rwbench/jinja/layout.html   |   29 +
 .../jinja2/examples/rwbench/mako/helpers.html   |   11 +
 .../jinja2/examples/rwbench/mako/index.html     |   31 +
 .../jinja2/examples/rwbench/mako/layout.html    |   30 +
 .../python/jinja2/examples/rwbench/rwbench.py   |  112 ++
 .../main/python/jinja2/ext/Vim/htmljinja.vim    |   27 +
 .../src/main/python/jinja2/ext/Vim/jinja.vim    |  113 ++
 .../jinja2/ext/django2jinja/django2jinja.py     |  768 ++++++++
 .../python/jinja2/ext/django2jinja/example.py   |    7 +
 .../ext/django2jinja/templates/index.html       |   58 +
 .../ext/django2jinja/templates/layout.html      |    4 +
 .../ext/django2jinja/templates/subtemplate.html |    1 +
 .../src/main/python/jinja2/ext/djangojinja2.py  |   86 +
 .../src/main/python/jinja2/ext/inlinegettext.py |   78 +
 .../src/main/python/jinja2/ext/jinja.el         |  213 +++
 .../src/main/python/jinja2/jinja2-debug.py      |   40 +
 .../src/main/python/jinja2/jinja2/__init__.py   |   73 +
 .../main/python/jinja2/jinja2/_debugsupport.c   |   78 +
 .../jinja2/jinja2/_markupsafe/__init__.py       |  225 +++
 .../python/jinja2/jinja2/_markupsafe/_bundle.py |   49 +
 .../jinja2/jinja2/_markupsafe/_constants.py     |  267 +++
 .../python/jinja2/jinja2/_markupsafe/_native.py |   45 +
 .../python/jinja2/jinja2/_markupsafe/tests.py   |   80 +
 .../main/python/jinja2/jinja2/_stringdefs.py    |  130 ++
 .../src/main/python/jinja2/jinja2/bccache.py    |  280 +++
 .../src/main/python/jinja2/jinja2/compiler.py   | 1640 ++++++++++++++++++
 .../src/main/python/jinja2/jinja2/constants.py  |   32 +
 .../src/main/python/jinja2/jinja2/debug.py      |  308 ++++
 .../src/main/python/jinja2/jinja2/defaults.py   |   40 +
 .../main/python/jinja2/jinja2/environment.py    | 1118 ++++++++++++
 .../src/main/python/jinja2/jinja2/exceptions.py |  143 ++
 .../src/main/python/jinja2/jinja2/ext.py        |  610 +++++++
 .../src/main/python/jinja2/jinja2/filters.py    |  719 ++++++++
 .../src/main/python/jinja2/jinja2/lexer.py      |  681 ++++++++
 .../src/main/python/jinja2/jinja2/loaders.py    |  449 +++++
 .../src/main/python/jinja2/jinja2/meta.py       |  102 ++
 .../src/main/python/jinja2/jinja2/nodes.py      |  901 ++++++++++
 .../src/main/python/jinja2/jinja2/optimizer.py  |   68 +
 .../src/main/python/jinja2/jinja2/parser.py     |  896 ++++++++++
 .../src/main/python/jinja2/jinja2/runtime.py    |  544 ++++++
 .../src/main/python/jinja2/jinja2/sandbox.py    |  271 +++
 .../src/main/python/jinja2/jinja2/tests.py      |  146 ++
 .../python/jinja2/jinja2/testsuite/__init__.py  |   95 +
 .../main/python/jinja2/jinja2/testsuite/api.py  |  240 +++
 .../python/jinja2/jinja2/testsuite/core_tags.py |  286 +++
 .../python/jinja2/jinja2/testsuite/debug.py     |   60 +
 .../python/jinja2/jinja2/testsuite/doctests.py  |   29 +
 .../main/python/jinja2/jinja2/testsuite/ext.py  |  455 +++++
 .../python/jinja2/jinja2/testsuite/filters.py   |  291 ++++
 .../python/jinja2/jinja2/testsuite/imports.py   |  144 ++
 .../jinja2/jinja2/testsuite/inheritance.py      |  208 +++
 .../python/jinja2/jinja2/testsuite/lexnparse.py |  390 +++++
 .../python/jinja2/jinja2/testsuite/loader.py    |  191 ++
 .../jinja2/jinja2/testsuite/regression.py       |  258 +++
 .../jinja2/testsuite/res/templates/broken.html  |    3 +
 .../testsuite/res/templates/foo/test.html       |    1 +
 .../testsuite/res/templates/syntaxerror.html    |    4 +
 .../jinja2/testsuite/res/templates/test.html    |    1 +
 .../python/jinja2/jinja2/testsuite/security.py  |  134 ++
 .../python/jinja2/jinja2/testsuite/tests.py     |   87 +
 .../python/jinja2/jinja2/testsuite/utils.py     |   85 +
 .../src/main/python/jinja2/jinja2/utils.py      |  601 +++++++
 .../src/main/python/jinja2/jinja2/visitor.py    |   87 +
 .../src/main/python/jinja2/scripts/pylintrc     |  301 ++++
 ambari-common/src/main/python/jinja2/setup.cfg  |    6 +
 ambari-common/src/main/python/jinja2/setup.py   |  110 ++
 .../python/resource_management/core/source.py   |    2 +-
 ambari-server/pom.xml                           |    2 +-
 ambari-server/src/test/python/unitTests.py      |    2 +-
 pom.xml                                         |    2 +-
 246 files changed, 21397 insertions(+), 21397 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-agent/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-agent/pom.xml b/ambari-agent/pom.xml
index f4cec91..a487aa7 100644
--- a/ambari-agent/pom.xml
+++ b/ambari-agent/pom.xml
@@ -40,7 +40,7 @@
     <agent.install.dir>/usr/lib/python2.6/site-packages/ambari_agent</agent.install.dir>
     <ambari_commons.install.dir>/usr/lib/ambari-agent/lib/ambari_commons</ambari_commons.install.dir>
     <resource_management.install.dir>/usr/lib/ambari-agent/lib/resource_management</resource_management.install.dir>
-    <jinja.install.dir>/usr/lib/python2.6/site-packages/ambari_jinja2</jinja.install.dir>
+    <jinja.install.dir>/usr/lib/python2.6/site-packages/jinja2</jinja.install.dir>
     <lib.dir>/usr/lib/ambari-agent/lib</lib.dir>
     <python.ver>python &gt;= 2.6</python.ver>
     <deb.python.ver>python (&gt;= 2.6)</deb.python.ver>
@@ -115,7 +115,7 @@
                 <argument>unitTests.py</argument>
               </arguments>
               <environmentVariables>
-                <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/main/python/resource_management:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/../ambari-common/src/main/python:${project.basedir}/src/main/python/ambari_agent:${project.basedir}/src/test/python/ambari_agent:${project.basedir}/src/test/python/resource_management:${project.basedir}/src/main/python:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/package/files:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HDFS/package/files:$PYTHONPATH</PYTHONPATH>
+                <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python/jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/main/python/resource_management:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/../ambari-common/src/main/python:${project.basedir}/src/main/python/ambari_agent:${project.basedir}/src/test/python/ambari_agent:${project.basedir}/src/test/python/resource_management:${project.basedir}/src/main/python:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/package/files:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HDFS/package/files:$PYTHONPATH</PYTHONPATH>
               </environmentVariables>
               <skip>${skipTests}</skip>
             </configuration>
@@ -255,9 +255,9 @@
               <groupname>root</groupname>
               <sources>
                 <source>
-                  <location>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2</location>
+                  <location>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2</location>
                   <excludes>
-                    <exclude>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite</exclude>
+                    <exclude>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2/testsuite</exclude>
                   </excludes>
                 </source>
               </sources>
@@ -413,8 +413,8 @@
               </mapper>
             </data>
             <data>
-              <src>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2</src>
-              <excludes>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite</excludes>
+              <src>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2</src>
+              <excludes>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2/testsuite</excludes>
               <type>directory</type>
               <mapper>
                 <type>perm</type>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-agent/src/test/python/resource_management/TestContentSources.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestContentSources.py b/ambari-agent/src/test/python/resource_management/TestContentSources.py
index 1c5e8a8..2527f30 100644
--- a/ambari-agent/src/test/python/resource_management/TestContentSources.py
+++ b/ambari-agent/src/test/python/resource_management/TestContentSources.py
@@ -27,7 +27,7 @@ from resource_management.core.source import DownloadSource
 from resource_management.core.source import Template
 from resource_management.core.source import InlineTemplate
 
-from ambari_jinja2 import UndefinedError, TemplateNotFound
+from jinja2 import UndefinedError, TemplateNotFound
 import urllib2
 import os
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/AUTHORS
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/AUTHORS b/ambari-common/src/main/python/ambari_jinja2/AUTHORS
deleted file mode 100644
index c6cd9ba..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/AUTHORS
+++ /dev/null
@@ -1,31 +0,0 @@
-Jinja is written and maintained by the Jinja Team and various
-contributors:
-
-Lead Developer:
-
-- Armin Ronacher <ar...@active-4.com>
-
-Developers:
-
-- Christoph Hack
-- Georg Brandl
-
-Contributors:
-
-- Bryan McLemore
-- Mickaël Guérin <ka...@crocobox.org>
-- Cameron Knight
-- Lawrence Journal-World.
-- David Cramer
-
-Patches and suggestions:
-
-- Ronny Pfannschmidt
-- Axel Böhm
-- Alexey Melchakov
-- Bryan McLemore
-- Clovis Fabricio (nosklo)
-- Cameron Knight
-- Peter van Dijk (Habbie)
-- Stefan Ebner
-- Rene Leonhardt

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/CHANGES
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/CHANGES b/ambari-common/src/main/python/ambari_jinja2/CHANGES
deleted file mode 100644
index 25b8aa4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/CHANGES
+++ /dev/null
@@ -1,235 +0,0 @@
-Jinja2 Changelog
-================
-
-Version 2.5.5
--------------
-(re-release of 2.5.4 with built documentation removed for filesize.
- Released on October 18th 2010)
-
-- built documentation is no longer part of release.
-
-Version 2.5.4
--------------
-(bugfix release, released on October 17th 2010)
-
-- Fixed extensions not loading properly with overlays.
-- Work around a bug in cpython for the debugger that causes segfaults
-  on 64bit big-endian architectures.
-
-Version 2.5.3
--------------
-(bugfix release, released on October 17th 2010)
-
-- fixed an operator precedence error introduced in 2.5.2.  Statements
-  like "-foo.bar" had their implicit parentheses applied around the
-  first part of the expression ("(-foo).bar") instead of the more
-  correct "-(foo.bar)".
-
-Version 2.5.2
--------------
-(bugfix release, released on August 18th 2010)
-
-- improved setup.py script to better work with assumptions people
-  might still have from it (``--with-speedups``).
-- fixed a packaging error that excluded the new debug support.
-
-Version 2.5.1
--------------
-(bugfix release, released on August 17th 2010)
-
-- StopIteration exceptions raised by functions called from templates
-  are now intercepted and converted to undefineds.  This solves a
-  lot of debugging grief.  (StopIteration is used internally to
-  abort template execution)
-- improved performance of macro calls slightly.
-- babel extraction can now properly extract newstyle gettext calls.
-- using the variable `num` in newstyle gettext for something else
-  than the pluralize count will no longer raise a :exc:`KeyError`.
-- removed builtin markup class and switched to markupsafe.  For backwards
-  compatibility the pure Python implementation still exists but is
-  pulled from markupsafe by the Jinja2 developers.  The debug support
-  went into a separate feature called "debugsupport" and is disabled
-  by default because it is only relevant for Python 2.4
-- fixed an issue with unary operators having the wrong precendence.
-
-Version 2.5
------------
-(codename Incoherence, relased on May 29th 2010)
-
-- improved the sort filter (should have worked like this for a
-  long time) by adding support for case insensitive searches.
-- fixed a bug for getattribute constant folding.
-- support for newstyle gettext translations which result in a
-  nicer in-template user interface and more consistent
-  catalogs. (:ref:`newstyle-gettext`)
-- it's now possible to register extensions after an environment
-  was created.
-
-Version 2.4.1
--------------
-(bugfix release, released on April 20th 2010)
-
-- fixed an error reporting bug for undefineds.
-
-Version 2.4
------------
-(codename Correlation, released on April 13th 2010)
-
-- the environment template loading functions now transparently
-  pass through a template object if it was passed to it.  This
-  makes it possible to import or extend from a template object
-  that was passed to the template.
-- added a :class:`ModuleLoader` that can load templates from
-  precompiled sources.  The environment now features a method
-  to compile the templates from a configured loader into a zip
-  file or folder.
-- the _speedups C extension now supports Python 3.
-- added support for autoescaping toggling sections and support
-  for evaluation contexts (:ref:`eval-context`).
-- extensions have a priority now.
-
-Version 2.3.1
--------------
-(bugfix release, released on February 19th 2010)
-
-- fixed an error reporting bug on all python versions
-- fixed an error reporting bug on Python 2.4
-
-Version 2.3
------------
-(3000 Pythons, released on February 10th 2010)
-
-- fixes issue with code generator that causes unbound variables
-  to be generated if set was used in if-blocks and other small
-  identifier problems.
-- include tags are now able to select between multiple templates
-  and take the first that exists, if a list of templates is
-  given.
-- fixed a problem with having call blocks in outer scopes that
-  have an argument that is also used as local variable in an
-  inner frame (#360).
-- greatly improved error message reporting (#339)
-- implicit tuple expressions can no longer be totally empty.
-  This change makes ``{% if %}...{% endif %}`` a syntax error
-  now. (#364)
-- added support for translator comments if extracted via babel.
-- added with-statement extension.
-- experimental Python 3 support.
-
-Version 2.2.1
--------------
-(bugfix release, released on September 14th 2009)
-
-- fixes some smaller problems for Jinja2 on Jython.
-
-Version 2.2
------------
-(codename Kong, released on September 13th 2009)
-
-- Include statements can now be marked with ``ignore missing`` to skip
-  non existing templates.
-- Priority of `not` raised.  It's now possible to write `not foo in bar`
-  as an alias to `foo not in bar` like in python.  Previously the grammar
-  required parentheses (`not (foo in bar)`) which was odd.
-- Fixed a bug that caused syntax errors when defining macros or using the
-  `{% call %}` tag inside loops.
-- Fixed a bug in the parser that made ``{{ foo[1, 2] }}`` impossible.
-- Made it possible to refer to names from outer scopes in included templates
-  that were unused in the callers frame (#327)
-- Fixed a bug that caused internal errors if names where used as iteration
-  variable and regular variable *after* the loop if that variable was unused
-  *before* the loop.  (#331)
-- Added support for optional `scoped` modifier to blocks.
-- Added support for line-comments.
-- Added the `meta` module.
-- Renamed (undocumented) attribute "overlay" to "overlayed" on the
-  environment because it was clashing with a method of the same name.
-- speedup extension is now disabled by default.
-
-Version 2.1.1
--------------
-(Bugfix release)
-
-- Fixed a translation error caused by looping over empty recursive loops.
-
-Version 2.1
------------
-(codename Yasuzō, released on November 23rd 2008)
-
-- fixed a bug with nested loops and the special loop variable.  Before the
-  change an inner loop overwrote the loop variable from the outer one after
-  iteration.
-
-- fixed a bug with the i18n extension that caused the explicit pluralization
-  block to look up the wrong variable.
-
-- fixed a limitation in the lexer that made ``{{ foo.0.0 }}`` impossible.
-
-- index based subscribing of variables with a constant value returns an
-  undefined object now instead of raising an index error.  This was a bug
-  caused by eager optimizing.
-
-- the i18n extension looks up `foo.ugettext` now followed by `foo.gettext`
-  if an translations object is installed.  This makes dealing with custom
-  translations classes easier.
-
-- fixed a confusing behavior with conditional extending.  loops were partially
-  executed under some conditions even though they were not part of a visible
-  area.
-
-- added `sort` filter that works like `dictsort` but for arbitrary sequences.
-
-- fixed a bug with empty statements in macros.
-
-- implemented a bytecode cache system.  (:ref:`bytecode-cache`)
-
-- the template context is now weakref-able
-
-- inclusions and imports "with context" forward all variables now, not only
-  the initial context.
-
-- added a cycle helper called `cycler`.
-
-- added a joining helper called `joiner`.
-
-- added a `compile_expression` method to the environment that allows compiling
-  of Jinja expressions into callable Python objects.
-
-- fixed an escaping bug in urlize
-
-Version 2.0
------------
-(codename jinjavitus, released on July 17th 2008)
-
-- the subscribing of objects (looking up attributes and items) changed from
-  slightly.  It's now possible to give attributes or items a higher priority
-  by either using dot-notation lookup or the bracket syntax.  This also
-  changed the AST slightly.  `Subscript` is gone and was replaced with
-  :class:`~ambari_jinja2.nodes.Getitem` and :class:`~ambari_jinja2.nodes.Getattr`.
-
-  For more information see :ref:`the implementation details <notes-on-subscriptions>`.
-
-- added support for preprocessing and token stream filtering for extensions.
-  This would allow extensions to allow simplified gettext calls in template
-  data and something similar.
-
-- added :meth:`ambari_jinja2.environment.TemplateStream.dump`.
-
-- added missing support for implicit string literal concatenation.
-  ``{{ "foo" "bar" }}`` is equivalent to ``{{ "foobar" }}``
-
-- `else` is optional for conditional expressions.  If not given it evaluates
-  to `false`.
-
-- improved error reporting for undefined values by providing a position.
-
-- `filesizeformat` filter uses decimal prefixes now per default and can be
-  set to binary mode with the second parameter.
-
-- fixed bug in finalizer
-
-Version 2.0rc1
---------------
-(no codename, released on June 9th 2008)
-
-- first release of Jinja2

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/LICENSE
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/LICENSE b/ambari-common/src/main/python/ambari_jinja2/LICENSE
deleted file mode 100644
index 31bf900..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/LICENSE
+++ /dev/null
@@ -1,31 +0,0 @@
-Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
-
-Some rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * The names of the contributors may not be used to endorse or
-      promote products derived from this software without specific
-      prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in b/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in
deleted file mode 100644
index 17ef0bd..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in
+++ /dev/null
@@ -1,12 +0,0 @@
-include MANIFEST.in Makefile CHANGES LICENSE AUTHORS ambari_jinja2/_debugsupport.c
-recursive-include docs *
-recursive-include custom_fixers *
-recursive-include ext *
-recursive-include artwork *
-recursive-include examples *
-recursive-include ambari_jinja2/testsuite/res *
-recursive-exclude docs/_build *
-recursive-exclude ambari_jinja2 *.pyc
-recursive-exclude docs *.pyc
-recursive-exclude ambari_jinja2 *.pyo
-recursive-exclude docs *.pyo

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/Makefile b/ambari-common/src/main/python/ambari_jinja2/Makefile
deleted file mode 100644
index 60ca1d7..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-test:
-	python setup.py test
-
-.PHONY: test

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py
deleted file mode 100644
index d02aab2..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2
-    ~~~~~~
-
-    Jinja2 is a template engine written in pure Python.  It provides a
-    Django inspired non-XML syntax but supports inline expressions and
-    an optional sandboxed environment.
-
-    Nutshell
-    --------
-
-    Here a small example of a Jinja2 template::
-
-        {% extends 'base.html' %}
-        {% block title %}Memberlist{% endblock %}
-        {% block content %}
-          <ul>
-          {% for user in users %}
-            <li><a href="{{ user.url }}">{{ user.username }}</a></li>
-          {% endfor %}
-          </ul>
-        {% endblock %}
-
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-__docformat__ = 'restructuredtext en'
-try:
-    __version__ = __import__('pkg_resources') \
-        .get_distribution('Jinja2').version
-except:
-    __version__ = 'unknown'
-
-# high level interface
-from ambari_jinja2.environment import Environment, Template
-
-# loaders
-from ambari_jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \
-     DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \
-     ModuleLoader
-
-# bytecode caches
-from ambari_jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
-     MemcachedBytecodeCache
-
-# undefined types
-from ambari_jinja2.runtime import Undefined, DebugUndefined, StrictUndefined
-
-# exceptions
-from ambari_jinja2.exceptions import TemplateError, UndefinedError, \
-     TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \
-     TemplateAssertionError
-
-# decorators and public utilities
-from ambari_jinja2.filters import environmentfilter, contextfilter, \
-     evalcontextfilter
-from ambari_jinja2.utils import Markup, escape, clear_caches, \
-     environmentfunction, evalcontextfunction, contextfunction, \
-     is_undefined
-
-__all__ = [
-    'Environment', 'Template', 'BaseLoader', 'FileSystemLoader',
-    'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader',
-    'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache',
-    'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined',
-    'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound',
-    'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError',
-    'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape',
-    'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined',
-    'evalcontextfilter', 'evalcontextfunction'
-]

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c
deleted file mode 100644
index 041c94f..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * ambari_jinja2._debugsupport
- * ~~~~~~~~~~~~~~~~~~~~
- *
- * C implementation of `tb_set_next`.
- *
- * :copyright: (c) 2010 by the Jinja Team.
- * :license: BSD.
- */
-
-#include <Python.h>
-
-
-static PyObject*
-tb_set_next(PyObject *self, PyObject *args)
-{
-	PyTracebackObject *tb, *old;
-	PyObject *next;
-
-	if (!PyArg_ParseTuple(args, "O!O:tb_set_next", &PyTraceBack_Type, &tb, &next))
-		return NULL;
-	if (next == Py_None)
-		next = NULL;
-	else if (!PyTraceBack_Check(next)) {
-		PyErr_SetString(PyExc_TypeError,
-				"tb_set_next arg 2 must be traceback or None");
-		return NULL;
-	}
-	else
-		Py_INCREF(next);
-
-	old = tb->tb_next;
-	tb->tb_next = (PyTracebackObject*)next;
-	Py_XDECREF(old);
-
-	Py_INCREF(Py_None);
-	return Py_None;
-}
-
-static PyMethodDef module_methods[] = {
-	{"tb_set_next", (PyCFunction)tb_set_next, METH_VARARGS,
-	 "Set the tb_next member of a traceback object."},
-	{NULL, NULL, 0, NULL}		/* Sentinel */
-};
-
-
-#if PY_MAJOR_VERSION < 3
-
-#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-init_debugsupport(void)
-{
-	Py_InitModule3("ambari_jinja2._debugsupport", module_methods, "");
-}
-
-#else /* Python 3.x module initialization */
-
-static struct PyModuleDef module_definition = {
-        PyModuleDef_HEAD_INIT,
-	"ambari_jinja2._debugsupport",
-	NULL,
-	-1,
-	module_methods,
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-PyMODINIT_FUNC
-PyInit__debugsupport(void)
-{
-	return PyModule_Create(&module_definition);
-}
-
-#endif

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py
deleted file mode 100644
index 74d0fe3..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    markupsafe
-    ~~~~~~~~~~
-
-    Implements a Markup string.
-
-    :copyright: (c) 2010 by Armin Ronacher.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-from itertools import imap
-
-
-__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
-
-
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
-_entity_re = re.compile(r'&([^;]+);')
-
-
-class Markup(unicode):
-    r"""Marks a string as being safe for inclusion in HTML/XML output without
-    needing to be escaped.  This implements the `__html__` interface a couple
-    of frameworks and web applications use.  :class:`Markup` is a direct
-    subclass of `unicode` and provides all the methods of `unicode` just that
-    it escapes arguments passed and always returns `Markup`.
-
-    The `escape` function returns markup objects so that double escaping can't
-    happen.
-
-    The constructor of the :class:`Markup` class can be used for three
-    different things:  When passed an unicode object it's assumed to be safe,
-    when passed an object with an HTML representation (has an `__html__`
-    method) that representation is used, otherwise the object passed is
-    converted into a unicode string and then assumed to be safe:
-
-    >>> Markup("Hello <em>World</em>!")
-    Markup(u'Hello <em>World</em>!')
-    >>> class Foo(object):
-    ...  def __html__(self):
-    ...   return '<a href="#">foo</a>'
-    ... 
-    >>> Markup(Foo())
-    Markup(u'<a href="#">foo</a>')
-
-    If you want object passed being always treated as unsafe you can use the
-    :meth:`escape` classmethod to create a :class:`Markup` object:
-
-    >>> Markup.escape("Hello <em>World</em>!")
-    Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
-
-    Operations on a markup string are markup aware which means that all
-    arguments are passed through the :func:`escape` function:
-
-    >>> em = Markup("<em>%s</em>")
-    >>> em % "foo & bar"
-    Markup(u'<em>foo &amp; bar</em>')
-    >>> strong = Markup("<strong>%(text)s</strong>")
-    >>> strong % {'text': '<blink>hacker here</blink>'}
-    Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
-    >>> Markup("<em>Hello</em> ") + "<foo>"
-    Markup(u'<em>Hello</em> &lt;foo&gt;')
-    """
-    __slots__ = ()
-
-    def __new__(cls, base=u'', encoding=None, errors='strict'):
-        if hasattr(base, '__html__'):
-            base = base.__html__()
-        if encoding is None:
-            return unicode.__new__(cls, base)
-        return unicode.__new__(cls, base, encoding, errors)
-
-    def __html__(self):
-        return self
-
-    def __add__(self, other):
-        if hasattr(other, '__html__') or isinstance(other, basestring):
-            return self.__class__(unicode(self) + unicode(escape(other)))
-        return NotImplemented
-
-    def __radd__(self, other):
-        if hasattr(other, '__html__') or isinstance(other, basestring):
-            return self.__class__(unicode(escape(other)) + unicode(self))
-        return NotImplemented
-
-    def __mul__(self, num):
-        if isinstance(num, (int, long)):
-            return self.__class__(unicode.__mul__(self, num))
-        return NotImplemented
-    __rmul__ = __mul__
-
-    def __mod__(self, arg):
-        if isinstance(arg, tuple):
-            arg = tuple(imap(_MarkupEscapeHelper, arg))
-        else:
-            arg = _MarkupEscapeHelper(arg)
-        return self.__class__(unicode.__mod__(self, arg))
-
-    def __repr__(self):
-        return '%s(%s)' % (
-            self.__class__.__name__,
-            unicode.__repr__(self)
-        )
-
-    def join(self, seq):
-        return self.__class__(unicode.join(self, imap(escape, seq)))
-    join.__doc__ = unicode.join.__doc__
-
-    def split(self, *args, **kwargs):
-        return map(self.__class__, unicode.split(self, *args, **kwargs))
-    split.__doc__ = unicode.split.__doc__
-
-    def rsplit(self, *args, **kwargs):
-        return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
-    rsplit.__doc__ = unicode.rsplit.__doc__
-
-    def splitlines(self, *args, **kwargs):
-        return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
-    splitlines.__doc__ = unicode.splitlines.__doc__
-
-    def unescape(self):
-        r"""Unescape markup again into an unicode string.  This also resolves
-        known HTML4 and XHTML entities:
-
-        >>> Markup("Main &raquo; <em>About</em>").unescape()
-        u'Main \xbb <em>About</em>'
-        """
-        from ambari_jinja2._markupsafe._constants import HTML_ENTITIES
-        def handle_match(m):
-            name = m.group(1)
-            if name in HTML_ENTITIES:
-                return unichr(HTML_ENTITIES[name])
-            try:
-                if name[:2] in ('#x', '#X'):
-                    return unichr(int(name[2:], 16))
-                elif name.startswith('#'):
-                    return unichr(int(name[1:]))
-            except ValueError:
-                pass
-            return u''
-        return _entity_re.sub(handle_match, unicode(self))
-
-    def striptags(self):
-        r"""Unescape markup into an unicode string and strip all tags.  This
-        also resolves known HTML4 and XHTML entities.  Whitespace is
-        normalized to one:
-
-        >>> Markup("Main &raquo;  <em>About</em>").striptags()
-        u'Main \xbb About'
-        """
-        stripped = u' '.join(_striptags_re.sub('', self).split())
-        return Markup(stripped).unescape()
-
-    @classmethod
-    def escape(cls, s):
-        """Escape the string.  Works like :func:`escape` with the difference
-        that for subclasses of :class:`Markup` this function would return the
-        correct subclass.
-        """
-        rv = escape(s)
-        if rv.__class__ is not cls:
-            return cls(rv)
-        return rv
-
-    def make_wrapper(name):
-        orig = getattr(unicode, name)
-        def func(self, *args, **kwargs):
-            args = _escape_argspec(list(args), enumerate(args))
-            _escape_argspec(kwargs, kwargs.iteritems())
-            return self.__class__(orig(self, *args, **kwargs))
-        func.__name__ = orig.__name__
-        func.__doc__ = orig.__doc__
-        return func
-
-    for method in '__getitem__', 'capitalize', \
-                  'title', 'lower', 'upper', 'replace', 'ljust', \
-                  'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
-                  'translate', 'expandtabs', 'swapcase', 'zfill':
-        locals()[method] = make_wrapper(method)
-
-    # new in python 2.5
-    if hasattr(unicode, 'partition'):
-        partition = make_wrapper('partition'),
-        rpartition = make_wrapper('rpartition')
-
-    # new in python 2.6
-    if hasattr(unicode, 'format'):
-        format = make_wrapper('format')
-
-    # not in python 3
-    if hasattr(unicode, '__getslice__'):
-        __getslice__ = make_wrapper('__getslice__')
-
-    del method, make_wrapper
-
-
-def _escape_argspec(obj, iterable):
-    """Helper for various string-wrapped functions."""
-    for key, value in iterable:
-        if hasattr(value, '__html__') or isinstance(value, basestring):
-            obj[key] = escape(value)
-    return obj
-
-
-class _MarkupEscapeHelper(object):
-    """Helper for Markup.__mod__"""
-
-    def __init__(self, obj):
-        self.obj = obj
-
-    __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
-    __str__ = lambda s: str(escape(s.obj))
-    __unicode__ = lambda s: unicode(escape(s.obj))
-    __repr__ = lambda s: str(escape(repr(s.obj)))
-    __int__ = lambda s: int(s.obj)
-    __float__ = lambda s: float(s.obj)
-
-
-# we have to import it down here as the speedups and native
-# modules imports the markup type which is define above.
-try:
-    from ambari_jinja2._markupsafe._speedups import escape, escape_silent, soft_unicode
-except ImportError:
-    from ambari_jinja2._markupsafe._native import escape, escape_silent, soft_unicode

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py
deleted file mode 100644
index de5d15e..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2._markupsafe._bundle
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    This script pulls in markupsafe from a source folder and
-    bundles it with Jinja2.  It does not pull in the speedups
-    module though.
-
-    :copyright: Copyright 2010 by the Jinja team, see AUTHORS.
-    :license: BSD, see LICENSE for details.
-"""
-import sys
-import os
-import re
-
-
-def rewrite_imports(lines):
-    for idx, line in enumerate(lines):
-        new_line = re.sub(r'(import|from)\s+markupsafe\b',
-                          r'\1 ambari_jinja2._markupsafe', line)
-        if new_line != line:
-            lines[idx] = new_line
-
-
-def main():
-    if len(sys.argv) != 2:
-        print 'error: only argument is path to markupsafe'
-        sys.exit(1)
-    basedir = os.path.dirname(__file__)
-    markupdir = sys.argv[1]
-    for filename in os.listdir(markupdir):
-        if filename.endswith('.py'):
-            f = open(os.path.join(markupdir, filename))
-            try:
-                lines = list(f)
-            finally:
-                f.close()
-            rewrite_imports(lines)
-            f = open(os.path.join(basedir, filename), 'w')
-            try:
-                for line in lines:
-                    f.write(line)
-            finally:
-                f.close()
-
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py
deleted file mode 100644
index 919bf03..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    markupsafe._constants
-    ~~~~~~~~~~~~~~~~~~~~~
-
-    Highlevel implementation of the Markup string.
-
-    :copyright: (c) 2010 by Armin Ronacher.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-HTML_ENTITIES = {
-    'AElig': 198,
-    'Aacute': 193,
-    'Acirc': 194,
-    'Agrave': 192,
-    'Alpha': 913,
-    'Aring': 197,
-    'Atilde': 195,
-    'Auml': 196,
-    'Beta': 914,
-    'Ccedil': 199,
-    'Chi': 935,
-    'Dagger': 8225,
-    'Delta': 916,
-    'ETH': 208,
-    'Eacute': 201,
-    'Ecirc': 202,
-    'Egrave': 200,
-    'Epsilon': 917,
-    'Eta': 919,
-    'Euml': 203,
-    'Gamma': 915,
-    'Iacute': 205,
-    'Icirc': 206,
-    'Igrave': 204,
-    'Iota': 921,
-    'Iuml': 207,
-    'Kappa': 922,
-    'Lambda': 923,
-    'Mu': 924,
-    'Ntilde': 209,
-    'Nu': 925,
-    'OElig': 338,
-    'Oacute': 211,
-    'Ocirc': 212,
-    'Ograve': 210,
-    'Omega': 937,
-    'Omicron': 927,
-    'Oslash': 216,
-    'Otilde': 213,
-    'Ouml': 214,
-    'Phi': 934,
-    'Pi': 928,
-    'Prime': 8243,
-    'Psi': 936,
-    'Rho': 929,
-    'Scaron': 352,
-    'Sigma': 931,
-    'THORN': 222,
-    'Tau': 932,
-    'Theta': 920,
-    'Uacute': 218,
-    'Ucirc': 219,
-    'Ugrave': 217,
-    'Upsilon': 933,
-    'Uuml': 220,
-    'Xi': 926,
-    'Yacute': 221,
-    'Yuml': 376,
-    'Zeta': 918,
-    'aacute': 225,
-    'acirc': 226,
-    'acute': 180,
-    'aelig': 230,
-    'agrave': 224,
-    'alefsym': 8501,
-    'alpha': 945,
-    'amp': 38,
-    'and': 8743,
-    'ang': 8736,
-    'apos': 39,
-    'aring': 229,
-    'asymp': 8776,
-    'atilde': 227,
-    'auml': 228,
-    'bdquo': 8222,
-    'beta': 946,
-    'brvbar': 166,
-    'bull': 8226,
-    'cap': 8745,
-    'ccedil': 231,
-    'cedil': 184,
-    'cent': 162,
-    'chi': 967,
-    'circ': 710,
-    'clubs': 9827,
-    'cong': 8773,
-    'copy': 169,
-    'crarr': 8629,
-    'cup': 8746,
-    'curren': 164,
-    'dArr': 8659,
-    'dagger': 8224,
-    'darr': 8595,
-    'deg': 176,
-    'delta': 948,
-    'diams': 9830,
-    'divide': 247,
-    'eacute': 233,
-    'ecirc': 234,
-    'egrave': 232,
-    'empty': 8709,
-    'emsp': 8195,
-    'ensp': 8194,
-    'epsilon': 949,
-    'equiv': 8801,
-    'eta': 951,
-    'eth': 240,
-    'euml': 235,
-    'euro': 8364,
-    'exist': 8707,
-    'fnof': 402,
-    'forall': 8704,
-    'frac12': 189,
-    'frac14': 188,
-    'frac34': 190,
-    'frasl': 8260,
-    'gamma': 947,
-    'ge': 8805,
-    'gt': 62,
-    'hArr': 8660,
-    'harr': 8596,
-    'hearts': 9829,
-    'hellip': 8230,
-    'iacute': 237,
-    'icirc': 238,
-    'iexcl': 161,
-    'igrave': 236,
-    'image': 8465,
-    'infin': 8734,
-    'int': 8747,
-    'iota': 953,
-    'iquest': 191,
-    'isin': 8712,
-    'iuml': 239,
-    'kappa': 954,
-    'lArr': 8656,
-    'lambda': 955,
-    'lang': 9001,
-    'laquo': 171,
-    'larr': 8592,
-    'lceil': 8968,
-    'ldquo': 8220,
-    'le': 8804,
-    'lfloor': 8970,
-    'lowast': 8727,
-    'loz': 9674,
-    'lrm': 8206,
-    'lsaquo': 8249,
-    'lsquo': 8216,
-    'lt': 60,
-    'macr': 175,
-    'mdash': 8212,
-    'micro': 181,
-    'middot': 183,
-    'minus': 8722,
-    'mu': 956,
-    'nabla': 8711,
-    'nbsp': 160,
-    'ndash': 8211,
-    'ne': 8800,
-    'ni': 8715,
-    'not': 172,
-    'notin': 8713,
-    'nsub': 8836,
-    'ntilde': 241,
-    'nu': 957,
-    'oacute': 243,
-    'ocirc': 244,
-    'oelig': 339,
-    'ograve': 242,
-    'oline': 8254,
-    'omega': 969,
-    'omicron': 959,
-    'oplus': 8853,
-    'or': 8744,
-    'ordf': 170,
-    'ordm': 186,
-    'oslash': 248,
-    'otilde': 245,
-    'otimes': 8855,
-    'ouml': 246,
-    'para': 182,
-    'part': 8706,
-    'permil': 8240,
-    'perp': 8869,
-    'phi': 966,
-    'pi': 960,
-    'piv': 982,
-    'plusmn': 177,
-    'pound': 163,
-    'prime': 8242,
-    'prod': 8719,
-    'prop': 8733,
-    'psi': 968,
-    'quot': 34,
-    'rArr': 8658,
-    'radic': 8730,
-    'rang': 9002,
-    'raquo': 187,
-    'rarr': 8594,
-    'rceil': 8969,
-    'rdquo': 8221,
-    'real': 8476,
-    'reg': 174,
-    'rfloor': 8971,
-    'rho': 961,
-    'rlm': 8207,
-    'rsaquo': 8250,
-    'rsquo': 8217,
-    'sbquo': 8218,
-    'scaron': 353,
-    'sdot': 8901,
-    'sect': 167,
-    'shy': 173,
-    'sigma': 963,
-    'sigmaf': 962,
-    'sim': 8764,
-    'spades': 9824,
-    'sub': 8834,
-    'sube': 8838,
-    'sum': 8721,
-    'sup': 8835,
-    'sup1': 185,
-    'sup2': 178,
-    'sup3': 179,
-    'supe': 8839,
-    'szlig': 223,
-    'tau': 964,
-    'there4': 8756,
-    'theta': 952,
-    'thetasym': 977,
-    'thinsp': 8201,
-    'thorn': 254,
-    'tilde': 732,
-    'times': 215,
-    'trade': 8482,
-    'uArr': 8657,
-    'uacute': 250,
-    'uarr': 8593,
-    'ucirc': 251,
-    'ugrave': 249,
-    'uml': 168,
-    'upsih': 978,
-    'upsilon': 965,
-    'uuml': 252,
-    'weierp': 8472,
-    'xi': 958,
-    'yacute': 253,
-    'yen': 165,
-    'yuml': 255,
-    'zeta': 950,
-    'zwj': 8205,
-    'zwnj': 8204
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py
deleted file mode 100644
index 97c8d35..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    markupsafe._native
-    ~~~~~~~~~~~~~~~~~~
-
-    Native Python implementation the C module is not compiled.
-
-    :copyright: (c) 2010 by Armin Ronacher.
-    :license: BSD, see LICENSE for more details.
-"""
-from ambari_jinja2._markupsafe import Markup
-
-
-def escape(s):
-    """Convert the characters &, <, >, ' and " in string s to HTML-safe
-    sequences.  Use this if you need to display text that might contain
-    such characters in HTML.  Marks return value as markup string.
-    """
-    if hasattr(s, '__html__'):
-        return s.__html__()
-    return Markup(unicode(s)
-        .replace('&', '&amp;')
-        .replace('>', '&gt;')
-        .replace('<', '&lt;')
-        .replace("'", '&#39;')
-        .replace('"', '&#34;')
-    )
-
-
-def escape_silent(s):
-    """Like :func:`escape` but converts `None` into an empty
-    markup string.
-    """
-    if s is None:
-        return Markup()
-    return escape(s)
-
-
-def soft_unicode(s):
-    """Make a string unicode if it isn't already.  That way a markup
-    string is not converted back to unicode.
-    """
-    if not isinstance(s, unicode):
-        s = unicode(s)
-    return s

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py
deleted file mode 100644
index 8e88bfe..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py
+++ /dev/null
@@ -1,80 +0,0 @@
-import gc
-import unittest
-from ambari_jinja2._markupsafe import Markup, escape, escape_silent
-
-
-class MarkupTestCase(unittest.TestCase):
-
-    def test_markup_operations(self):
-        # adding two strings should escape the unsafe one
-        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
-        safe = Markup('<em>username</em>')
-        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
-
-        # string interpolations are safe to use too
-        assert Markup('<em>%s</em>') % '<bad user>' == \
-               '<em>&lt;bad user&gt;</em>'
-        assert Markup('<em>%(username)s</em>') % {
-            'username': '<bad user>'
-        } == '<em>&lt;bad user&gt;</em>'
-
-        # an escaped object is markup too
-        assert type(Markup('foo') + 'bar') is Markup
-
-        # and it implements __html__ by returning itself
-        x = Markup("foo")
-        assert x.__html__() is x
-
-        # it also knows how to treat __html__ objects
-        class Foo(object):
-            def __html__(self):
-                return '<em>awesome</em>'
-            def __unicode__(self):
-                return 'awesome'
-        assert Markup(Foo()) == '<em>awesome</em>'
-        assert Markup('<strong>%s</strong>') % Foo() == \
-               '<strong><em>awesome</em></strong>'
-
-        # escaping and unescaping
-        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
-        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
-        assert Markup("&lt;test&gt;").unescape() == "<test>"
-
-    def test_all_set(self):
-        import ambari_jinja2._markupsafe as markup
-        for item in markup.__all__:
-            getattr(markup, item)
-
-    def test_escape_silent(self):
-        assert escape_silent(None) == Markup()
-        assert escape(None) == Markup(None)
-        assert escape_silent('<foo>') == Markup(u'&lt;foo&gt;')
-
-
-class MarkupLeakTestCase(unittest.TestCase):
-
-    def test_markup_leaks(self):
-        counts = set()
-        for count in xrange(20):
-            for item in xrange(1000):
-                escape("foo")
-                escape("<foo>")
-                escape(u"foo")
-                escape(u"<foo>")
-            counts.add(len(gc.get_objects()))
-        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(MarkupTestCase))
-
-    # this test only tests the c extension
-    if not hasattr(escape, 'func_code'):
-        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
-
-    return suite
-
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='suite')


[12/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/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
deleted file mode 100644
index 0f4f982..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/bench.py
+++ /dev/null
@@ -1,433 +0,0 @@
-"""\
-    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/570de228/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
deleted file mode 100644
index 33de2a0..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/profile.py
+++ /dev/null
@@ -1,52 +0,0 @@
-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/570de228/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
deleted file mode 100644
index 9c4f710..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_form.html
+++ /dev/null
@@ -1 +0,0 @@
-<form action="{{ action }}" method="{{ method }}">{{ body }}</form>

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

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

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/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
deleted file mode 100644
index 6f620bb..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% 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/570de228/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
deleted file mode 100644
index 60039ce..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/layout.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!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/570de228/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
deleted file mode 100644
index 9e9fa6c..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/djangoext.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- 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/570de228/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
deleted file mode 100644
index ecc6dc4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/helpers.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<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/570de228/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
deleted file mode 100644
index 70f697d..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/index.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<?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/570de228/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
deleted file mode 100644
index b12aec4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/layout.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<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/570de228/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
deleted file mode 100644
index 89976aa..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/helpers.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% 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/570de228/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
deleted file mode 100644
index b006d05..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% 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/570de228/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
deleted file mode 100644
index 755789e..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/layout.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!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/570de228/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
deleted file mode 100644
index a0290eb..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/helpers.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<%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/570de228/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
deleted file mode 100644
index c4c6303..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/index.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<%!
-  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/570de228/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
deleted file mode 100644
index a9c353e..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/layout.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!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/570de228/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
deleted file mode 100644
index 35c7a1d..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/rwbench.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# -*- 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/570de228/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
deleted file mode 100644
index 3f9cba4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/Vim/htmljinja.vim
+++ /dev/null
@@ -1,27 +0,0 @@
-" 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/570de228/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
deleted file mode 100644
index 919954b..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/Vim/jinja.vim
+++ /dev/null
@@ -1,113 +0,0 @@
-" 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/570de228/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
deleted file mode 100644
index d2f3b0d..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/django2jinja.py
+++ /dev/null
@@ -1,768 +0,0 @@
-# -*- 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/570de228/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
deleted file mode 100644
index 2d4ab9a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/example.py
+++ /dev/null
@@ -1,7 +0,0 @@
-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/570de228/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
deleted file mode 100644
index d0fbe38..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% 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/570de228/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
deleted file mode 100644
index 3f21a12..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/layout.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<title>{% block title %}{% endblock %}</title>
-<div class="body">
-  {% block page-body %}{% endblock %}
-</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/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
deleted file mode 100644
index 980a0d5..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/subtemplate.html
+++ /dev/null
@@ -1 +0,0 @@
-Hello World!

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/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
deleted file mode 100644
index 9032400..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/djangojinja2.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# -*- 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/570de228/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
deleted file mode 100644
index ba585f3..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/inlinegettext.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- 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)


[16/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py
deleted file mode 100644
index 020c82a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py
+++ /dev/null
@@ -1,271 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.sandbox
-    ~~~~~~~~~~~~~~
-
-    Adds a sandbox layer to Jinja as it was the default behavior in the old
-    Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
-    default behavior is easier to use.
-
-    The behavior can be changed by subclassing the environment.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-import operator
-from ambari_jinja2.runtime import Undefined
-from ambari_jinja2.environment import Environment
-from ambari_jinja2.exceptions import SecurityError
-from ambari_jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
-     FrameType, GeneratorType
-
-
-#: maximum number of items a range may produce
-MAX_RANGE = 100000
-
-#: attributes of function objects that are considered unsafe.
-UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
-                                  'func_defaults', 'func_globals'])
-
-#: unsafe method attributes.  function attributes are unsafe for methods too
-UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
-
-
-import warnings
-
-# make sure we don't warn in python 2.6 about stuff we don't care about
-warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
-                        module='ambari_jinja2.sandbox')
-
-from collections import deque
-
-_mutable_set_types = (set,)
-_mutable_mapping_types = (dict,)
-_mutable_sequence_types = (list,)
-
-
-# on python 2.x we can register the user collection types
-try:
-    from UserDict import UserDict, DictMixin
-    from UserList import UserList
-    _mutable_mapping_types += (UserDict, DictMixin)
-    _mutable_set_types += (UserList,)
-except ImportError:
-    pass
-
-# if sets is still available, register the mutable set from there as well
-try:
-    from sets import Set
-    _mutable_set_types += (Set,)
-except ImportError:
-    pass
-
-#: register Python 2.6 abstract base classes
-try:
-    from collections import MutableSet, MutableMapping, MutableSequence
-    _mutable_set_types += (MutableSet,)
-    _mutable_mapping_types += (MutableMapping,)
-    _mutable_sequence_types += (MutableSequence,)
-except ImportError:
-    pass
-
-_mutable_spec = (
-    (_mutable_set_types, frozenset([
-        'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
-        'symmetric_difference_update', 'update'
-    ])),
-    (_mutable_mapping_types, frozenset([
-        'clear', 'pop', 'popitem', 'setdefault', 'update'
-    ])),
-    (_mutable_sequence_types, frozenset([
-        'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
-    ])),
-    (deque, frozenset([
-        'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
-        'popleft', 'remove', 'rotate'
-    ]))
-)
-
-
-def safe_range(*args):
-    """A range that can't generate ranges with a length of more than
-    MAX_RANGE items.
-    """
-    rng = xrange(*args)
-    if len(rng) > MAX_RANGE:
-        raise OverflowError('range too big, maximum size for range is %d' %
-                            MAX_RANGE)
-    return rng
-
-
-def unsafe(f):
-    """
-    Mark a function or method as unsafe::
-
-        @unsafe
-        def delete(self):
-            pass
-    """
-    f.unsafe_callable = True
-    return f
-
-
-def is_internal_attribute(obj, attr):
-    """Test if the attribute given is an internal python attribute.  For
-    example this function returns `True` for the `func_code` attribute of
-    python objects.  This is useful if the environment method
-    :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
-
-    >>> from ambari_jinja2.sandbox import is_internal_attribute
-    >>> is_internal_attribute(lambda: None, "func_code")
-    True
-    >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
-    True
-    >>> is_internal_attribute(str, "upper")
-    False
-    """
-    if isinstance(obj, FunctionType):
-        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
-            return True
-    elif isinstance(obj, MethodType):
-        if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
-           attr in UNSAFE_METHOD_ATTRIBUTES:
-            return True
-    elif isinstance(obj, type):
-        if attr == 'mro':
-            return True
-    elif isinstance(obj, (CodeType, TracebackType, FrameType)):
-        return True
-    elif isinstance(obj, GeneratorType):
-        if attr == 'gi_frame':
-            return True
-    return attr.startswith('__')
-
-
-def modifies_known_mutable(obj, attr):
-    """This function checks if an attribute on a builtin mutable object
-    (list, dict, set or deque) would modify it if called.  It also supports
-    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
-    with Python 2.6 onwards the abstract base classes `MutableSet`,
-    `MutableMapping`, and `MutableSequence`.
-
-    >>> modifies_known_mutable({}, "clear")
-    True
-    >>> modifies_known_mutable({}, "keys")
-    False
-    >>> modifies_known_mutable([], "append")
-    True
-    >>> modifies_known_mutable([], "index")
-    False
-
-    If called with an unsupported object (such as unicode) `False` is
-    returned.
-
-    >>> modifies_known_mutable("foo", "upper")
-    False
-    """
-    for typespec, unsafe in _mutable_spec:
-        if isinstance(obj, typespec):
-            return attr in unsafe
-    return False
-
-
-class SandboxedEnvironment(Environment):
-    """The sandboxed environment.  It works like the regular environment but
-    tells the compiler to generate sandboxed code.  Additionally subclasses of
-    this environment may override the methods that tell the runtime what
-    attributes or functions are safe to access.
-
-    If the template tries to access insecure code a :exc:`SecurityError` is
-    raised.  However also other exceptions may occour during the rendering so
-    the caller has to ensure that all exceptions are catched.
-    """
-    sandboxed = True
-
-    def __init__(self, *args, **kwargs):
-        Environment.__init__(self, *args, **kwargs)
-        self.globals['range'] = safe_range
-
-    def is_safe_attribute(self, obj, attr, value):
-        """The sandboxed environment will call this method to check if the
-        attribute of an object is safe to access.  Per default all attributes
-        starting with an underscore are considered private as well as the
-        special attributes of internal python objects as returned by the
-        :func:`is_internal_attribute` function.
-        """
-        return not (attr.startswith('_') or is_internal_attribute(obj, attr))
-
-    def is_safe_callable(self, obj):
-        """Check if an object is safely callable.  Per default a function is
-        considered safe unless the `unsafe_callable` attribute exists and is
-        True.  Override this method to alter the behavior, but this won't
-        affect the `unsafe` decorator from this module.
-        """
-        return not (getattr(obj, 'unsafe_callable', False) or \
-                    getattr(obj, 'alters_data', False))
-
-    def getitem(self, obj, argument):
-        """Subscribe an object from sandboxed code."""
-        try:
-            return obj[argument]
-        except (TypeError, LookupError):
-            if isinstance(argument, basestring):
-                try:
-                    attr = str(argument)
-                except:
-                    pass
-                else:
-                    try:
-                        value = getattr(obj, attr)
-                    except AttributeError:
-                        pass
-                    else:
-                        if self.is_safe_attribute(obj, argument, value):
-                            return value
-                        return self.unsafe_undefined(obj, argument)
-        return self.undefined(obj=obj, name=argument)
-
-    def getattr(self, obj, attribute):
-        """Subscribe an object from sandboxed code and prefer the
-        attribute.  The attribute passed *must* be a bytestring.
-        """
-        try:
-            value = getattr(obj, attribute)
-        except AttributeError:
-            try:
-                return obj[attribute]
-            except (TypeError, LookupError):
-                pass
-        else:
-            if self.is_safe_attribute(obj, attribute, value):
-                return value
-            return self.unsafe_undefined(obj, attribute)
-        return self.undefined(obj=obj, name=attribute)
-
-    def unsafe_undefined(self, obj, attribute):
-        """Return an undefined object for unsafe attributes."""
-        return self.undefined('access to attribute %r of %r '
-                              'object is unsafe.' % (
-            attribute,
-            obj.__class__.__name__
-        ), name=attribute, obj=obj, exc=SecurityError)
-
-    def call(__self, __context, __obj, *args, **kwargs):
-        """Call an object from sandboxed code."""
-        # the double prefixes are to avoid double keyword argument
-        # errors when proxying the call.
-        if not __self.is_safe_callable(__obj):
-            raise SecurityError('%r is not safely callable' % (__obj,))
-        return __context.call(__obj, *args, **kwargs)
-
-
-class ImmutableSandboxedEnvironment(SandboxedEnvironment):
-    """Works exactly like the regular `SandboxedEnvironment` but does not
-    permit modifications on the builtin mutable objects `list`, `set`, and
-    `dict` by using the :func:`modifies_known_mutable` function.
-    """
-
-    def is_safe_attribute(self, obj, attr, value):
-        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
-            return False
-        return not modifies_known_mutable(obj, attr)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py
deleted file mode 100644
index 4cb2bbf..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.tests
-    ~~~~~~~~~~~~
-
-    Jinja test functions. Used with the "is" operator.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-from ambari_jinja2.runtime import Undefined
-
-# nose, nothing here to test
-__test__ = False
-
-
-number_re = re.compile(r'^-?\d+(\.\d+)?$')
-regex_type = type(number_re)
-
-
-try:
-    test_callable = callable
-except NameError:
-    def test_callable(x):
-        return hasattr(x, '__call__')
-
-
-def test_odd(value):
-    """Return true if the variable is odd."""
-    return value % 2 == 1
-
-
-def test_even(value):
-    """Return true if the variable is even."""
-    return value % 2 == 0
-
-
-def test_divisibleby(value, num):
-    """Check if a variable is divisible by a number."""
-    return value % num == 0
-
-
-def test_defined(value):
-    """Return true if the variable is defined:
-
-    .. sourcecode:: jinja
-
-        {% if variable is defined %}
-            value of variable: {{ variable }}
-        {% else %}
-            variable is not defined
-        {% endif %}
-
-    See the :func:`default` filter for a simple way to set undefined
-    variables.
-    """
-    return not isinstance(value, Undefined)
-
-
-def test_undefined(value):
-    """Like :func:`defined` but the other way round."""
-    return isinstance(value, Undefined)
-
-
-def test_none(value):
-    """Return true if the variable is none."""
-    return value is None
-
-
-def test_lower(value):
-    """Return true if the variable is lowercased."""
-    return unicode(value).islower()
-
-
-def test_upper(value):
-    """Return true if the variable is uppercased."""
-    return unicode(value).isupper()
-
-
-def test_string(value):
-    """Return true if the object is a string."""
-    return isinstance(value, basestring)
-
-
-def test_number(value):
-    """Return true if the variable is a number."""
-    return isinstance(value, (int, long, float, complex))
-
-
-def test_sequence(value):
-    """Return true if the variable is a sequence. Sequences are variables
-    that are iterable.
-    """
-    try:
-        len(value)
-        value.__getitem__
-    except:
-        return False
-    return True
-
-
-def test_sameas(value, other):
-    """Check if an object points to the same memory address than another
-    object:
-
-    .. sourcecode:: jinja
-
-        {% if foo.attribute is sameas false %}
-            the foo attribute really is the `False` singleton
-        {% endif %}
-    """
-    return value is other
-
-
-def test_iterable(value):
-    """Check if it's possible to iterate over an object."""
-    try:
-        iter(value)
-    except TypeError:
-        return False
-    return True
-
-
-def test_escaped(value):
-    """Check if the value is escaped."""
-    return hasattr(value, '__html__')
-
-
-TESTS = {
-    'odd':              test_odd,
-    'even':             test_even,
-    'divisibleby':      test_divisibleby,
-    'defined':          test_defined,
-    'undefined':        test_undefined,
-    'none':             test_none,
-    'lower':            test_lower,
-    'upper':            test_upper,
-    'string':           test_string,
-    'number':           test_number,
-    'sequence':         test_sequence,
-    'iterable':         test_iterable,
-    'callable':         test_callable,
-    'sameas':           test_sameas,
-    'escaped':          test_escaped
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py
deleted file mode 100644
index cd11117..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite
-    ~~~~~~~~~~~~~~~~
-
-    All the unittests of Jinja2.  These tests can be executed by
-    either running run-tests.py using multiple Python versions at
-    the same time.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import re
-import sys
-import unittest
-from traceback import format_exception
-from ambari_jinja2 import loaders
-
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-dict_loader = loaders.DictLoader({
-    'justdict.html':        'FOO'
-})
-package_loader = loaders.PackageLoader('ambari_jinja2.testsuite.res', 'templates')
-filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
-function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
-choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
-prefix_loader = loaders.PrefixLoader({
-    'a':        filesystem_loader,
-    'b':        dict_loader
-})
-
-
-class JinjaTestCase(unittest.TestCase):
-
-    ### use only these methods for testing.  If you need standard
-    ### unittest method, wrap them!
-
-    def setup(self):
-        pass
-
-    def teardown(self):
-        pass
-
-    def setUp(self):
-        self.setup()
-
-    def tearDown(self):
-        self.teardown()
-
-    def assert_equal(self, a, b):
-        return self.assertEqual(a, b)
-
-    def assert_raises(self, *args, **kwargs):
-        return self.assertRaises(*args, **kwargs)
-
-    def assert_traceback_matches(self, callback, expected_tb):
-        try:
-            callback()
-        except Exception, e:
-            tb = format_exception(*sys.exc_info())
-            if re.search(expected_tb.strip(), ''.join(tb)) is None:
-                raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
-                    % (''.join(tb), expected_tb))
-        else:
-            self.fail('Expected exception')
-
-
-def suite():
-    from ambari_jinja2.testsuite import ext, filters, tests, core_tags, \
-         loader, inheritance, imports, lexnparse, security, api, \
-         regression, debug, utils, doctests
-    suite = unittest.TestSuite()
-    suite.addTest(ext.suite())
-    suite.addTest(filters.suite())
-    suite.addTest(tests.suite())
-    suite.addTest(core_tags.suite())
-    suite.addTest(loader.suite())
-    suite.addTest(inheritance.suite())
-    suite.addTest(imports.suite())
-    suite.addTest(lexnparse.suite())
-    suite.addTest(security.suite())
-    suite.addTest(api.suite())
-    suite.addTest(regression.suite())
-    suite.addTest(debug.suite())
-    suite.addTest(utils.suite())
-
-    # doctests will not run on python 3 currently.  Too many issues
-    # with that, do not test that on that platform.
-    if sys.version_info < (3, 0):
-        suite.addTest(doctests.suite())
-
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py
deleted file mode 100644
index a02fb60..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py
+++ /dev/null
@@ -1,240 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.api
-    ~~~~~~~~~~~~~~~~~~~~
-
-    Tests the public API and related stuff.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment, Undefined, DebugUndefined, \
-     StrictUndefined, UndefinedError, Template, meta, \
-     is_undefined, Template, DictLoader
-from ambari_jinja2.utils import Cycler
-
-env = Environment()
-
-
-class ExtendedAPITestCase(JinjaTestCase):
-
-    def test_item_and_attribute(self):
-        from ambari_jinja2.sandbox import SandboxedEnvironment
-
-        for env in Environment(), SandboxedEnvironment():
-            # the |list is necessary for python3
-            tmpl = env.from_string('{{ foo.items()|list }}')
-            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
-            tmpl = env.from_string('{{ foo|attr("items")()|list }}')
-            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
-            tmpl = env.from_string('{{ foo["items"] }}')
-            assert tmpl.render(foo={'items': 42}) == '42'
-
-    def test_finalizer(self):
-        def finalize_none_empty(value):
-            if value is None:
-                value = u''
-            return value
-        env = Environment(finalize=finalize_none_empty)
-        tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
-        assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo'
-        tmpl = env.from_string('<{{ none }}>')
-        assert tmpl.render() == '<>'
-
-    def test_cycler(self):
-        items = 1, 2, 3
-        c = Cycler(*items)
-        for item in items + items:
-            assert c.current == item
-            assert c.next() == item
-        c.next()
-        assert c.current == 2
-        c.reset()
-        assert c.current == 1
-
-    def test_expressions(self):
-        expr = env.compile_expression("foo")
-        assert expr() is None
-        assert expr(foo=42) == 42
-        expr2 = env.compile_expression("foo", undefined_to_none=False)
-        assert is_undefined(expr2())
-
-        expr = env.compile_expression("42 + foo")
-        assert expr(foo=42) == 84
-
-    def test_template_passthrough(self):
-        t = Template('Content')
-        assert env.get_template(t) is t
-        assert env.select_template([t]) is t
-        assert env.get_or_select_template([t]) is t
-        assert env.get_or_select_template(t) is t
-
-    def test_autoescape_autoselect(self):
-        def select_autoescape(name):
-            if name is None or '.' not in name:
-                return False
-            return name.endswith('.html')
-        env = Environment(autoescape=select_autoescape,
-                          loader=DictLoader({
-            'test.txt':     '{{ foo }}',
-            'test.html':    '{{ foo }}'
-        }))
-        t = env.get_template('test.txt')
-        assert t.render(foo='<foo>') == '<foo>'
-        t = env.get_template('test.html')
-        assert t.render(foo='<foo>') == '&lt;foo&gt;'
-        t = env.from_string('{{ foo }}')
-        assert t.render(foo='<foo>') == '<foo>'
-
-
-class MetaTestCase(JinjaTestCase):
-
-    def test_find_undeclared_variables(self):
-        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
-        x = meta.find_undeclared_variables(ast)
-        assert x == set(['bar'])
-
-        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
-                        '{% macro meh(x) %}{{ x }}{% endmacro %}'
-                        '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
-        x = meta.find_undeclared_variables(ast)
-        assert x == set(['bar', 'seq', 'muh'])
-
-    def test_find_refererenced_templates(self):
-        ast = env.parse('{% extends "layout.html" %}{% include helper %}')
-        i = meta.find_referenced_templates(ast)
-        assert i.next() == 'layout.html'
-        assert i.next() is None
-        assert list(i) == []
-
-        ast = env.parse('{% extends "layout.html" %}'
-                        '{% from "test.html" import a, b as c %}'
-                        '{% import "meh.html" as meh %}'
-                        '{% include "muh.html" %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
-
-    def test_find_included_templates(self):
-        ast = env.parse('{% include ["foo.html", "bar.html"] %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html']
-
-        ast = env.parse('{% include ("foo.html", "bar.html") %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html']
-
-        ast = env.parse('{% include ["foo.html", "bar.html", foo] %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html', None]
-
-        ast = env.parse('{% include ("foo.html", "bar.html", foo) %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html', None]
-
-
-class StreamingTestCase(JinjaTestCase):
-
-    def test_basic_streaming(self):
-        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
-                               "}} - {{ item }}</li>{%- endfor %}</ul>")
-        stream = tmpl.stream(seq=range(4))
-        self.assert_equal(stream.next(), '<ul>')
-        self.assert_equal(stream.next(), '<li>1 - 0</li>')
-        self.assert_equal(stream.next(), '<li>2 - 1</li>')
-        self.assert_equal(stream.next(), '<li>3 - 2</li>')
-        self.assert_equal(stream.next(), '<li>4 - 3</li>')
-        self.assert_equal(stream.next(), '</ul>')
-
-    def test_buffered_streaming(self):
-        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
-                               "}} - {{ item }}</li>{%- endfor %}</ul>")
-        stream = tmpl.stream(seq=range(4))
-        stream.enable_buffering(size=3)
-        self.assert_equal(stream.next(), u'<ul><li>1 - 0</li><li>2 - 1</li>')
-        self.assert_equal(stream.next(), u'<li>3 - 2</li><li>4 - 3</li></ul>')
-
-    def test_streaming_behavior(self):
-        tmpl = env.from_string("")
-        stream = tmpl.stream()
-        assert not stream.buffered
-        stream.enable_buffering(20)
-        assert stream.buffered
-        stream.disable_buffering()
-        assert not stream.buffered
-
-
-class UndefinedTestCase(JinjaTestCase):
-
-    def test_stopiteration_is_undefined(self):
-        def test():
-            raise StopIteration()
-        t = Template('A{{ test() }}B')
-        assert t.render(test=test) == 'AB'
-        t = Template('A{{ test().missingattribute }}B')
-        self.assert_raises(UndefinedError, t.render, test=test)
-
-    def test_default_undefined(self):
-        env = Environment(undefined=Undefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), u'')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
-    def test_debug_undefined(self):
-        env = Environment(undefined=DebugUndefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
-                          u"{{ no such element: int object['missing'] }}")
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
-    def test_strict_undefined(self):
-        env = Environment(undefined=StrictUndefined)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
-        self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
-
-    def test_indexing_gives_undefined(self):
-        t = Template("{{ var[42].foo }}")
-        self.assert_raises(UndefinedError, t.render, var=0)
-
-    def test_none_gives_proper_error(self):
-        try:
-            Environment().getattr(None, 'split')()
-        except UndefinedError, e:
-            assert e.message == "'None' has no attribute 'split'"
-        else:
-            assert False, 'expected exception'
-
-    def test_object_repr(self):
-        try:
-            Undefined(obj=42, name='upper')()
-        except UndefinedError, e:
-            assert e.message == "'int object' has no attribute 'upper'"
-        else:
-            assert False, 'expected exception'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
-    suite.addTest(unittest.makeSuite(MetaTestCase))
-    suite.addTest(unittest.makeSuite(StreamingTestCase))
-    suite.addTest(unittest.makeSuite(UndefinedTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py
deleted file mode 100644
index 37e3c50..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py
+++ /dev/null
@@ -1,286 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.core_tags
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Test the core tags like for and if.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
-     DictLoader
-
-env = Environment()
-
-
-class ForLoopTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
-        assert tmpl.render(seq=range(10)) == '0123456789'
-
-    def test_else(self):
-        tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
-        assert tmpl.render() == '...'
-
-    def test_empty_blocks(self):
-        tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
-        assert tmpl.render() == '<>'
-
-    def test_context_vars(self):
-        tmpl = env.from_string('''{% for item in seq -%}
-        {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
-            loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
-           loop.length }}###{% endfor %}''')
-        one, two, _ = tmpl.render(seq=[0, 1]).split('###')
-        (one_index, one_index0, one_revindex, one_revindex0, one_first,
-         one_last, one_length) = one.split('|')
-        (two_index, two_index0, two_revindex, two_revindex0, two_first,
-         two_last, two_length) = two.split('|')
-
-        assert int(one_index) == 1 and int(two_index) == 2
-        assert int(one_index0) == 0 and int(two_index0) == 1
-        assert int(one_revindex) == 2 and int(two_revindex) == 1
-        assert int(one_revindex0) == 1 and int(two_revindex0) == 0
-        assert one_first == 'True' and two_first == 'False'
-        assert one_last == 'False' and two_last == 'True'
-        assert one_length == two_length == '2'
-
-    def test_cycling(self):
-        tmpl = env.from_string('''{% for item in seq %}{{
-            loop.cycle('<1>', '<2>') }}{% endfor %}{%
-            for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
-        output = tmpl.render(seq=range(4), through=('<1>', '<2>'))
-        assert output == '<1><2>' * 4
-
-    def test_scope(self):
-        tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
-        output = tmpl.render(seq=range(10))
-        assert not output
-
-    def test_varlen(self):
-        def inner():
-            for item in range(5):
-                yield item
-        tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}')
-        output = tmpl.render(iter=inner())
-        assert output == '01234'
-
-    def test_noniter(self):
-        tmpl = env.from_string('{% for item in none %}...{% endfor %}')
-        self.assert_raises(TypeError, tmpl.render)
-
-    def test_recursive(self):
-        tmpl = env.from_string('''{% for item in seq recursive -%}
-            [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
-        {%- endfor %}''')
-        assert tmpl.render(seq=[
-            dict(a=1, b=[dict(a=1), dict(a=2)]),
-            dict(a=2, b=[dict(a=1), dict(a=2)]),
-            dict(a=3, b=[dict(a='a')])
-        ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
-
-    def test_looploop(self):
-        tmpl = env.from_string('''{% for row in table %}
-            {%- set rowloop = loop -%}
-            {% for cell in row -%}
-                [{{ rowloop.index }}|{{ loop.index }}]
-            {%- endfor %}
-        {%- endfor %}''')
-        assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
-
-    def test_reversed_bug(self):
-        tmpl = env.from_string('{% for i in items %}{{ i }}'
-                               '{% if not loop.last %}'
-                               ',{% endif %}{% endfor %}')
-        assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
-
-    def test_loop_errors(self):
-        tmpl = env.from_string('''{% for item in [1] if loop.index
-                                      == 0 %}...{% endfor %}''')
-        self.assert_raises(UndefinedError, tmpl.render)
-        tmpl = env.from_string('''{% for item in [] %}...{% else
-            %}{{ loop }}{% endfor %}''')
-        assert tmpl.render() == ''
-
-    def test_loop_filter(self):
-        tmpl = env.from_string('{% for item in range(10) if item '
-                               'is even %}[{{ item }}]{% endfor %}')
-        assert tmpl.render() == '[0][2][4][6][8]'
-        tmpl = env.from_string('''
-            {%- for item in range(10) if item is even %}[{{
-                loop.index }}:{{ item }}]{% endfor %}''')
-        assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
-
-    def test_loop_unassignable(self):
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{% for loop in seq %}...{% endfor %}')
-
-    def test_scoped_special_var(self):
-        t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
-                            '|{{ loop.first }}{% endfor %}]{% endfor %}')
-        assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
-
-    def test_scoped_loop_var(self):
-        t = env.from_string('{% for x in seq %}{{ loop.first }}'
-                            '{% for y in seq %}{% endfor %}{% endfor %}')
-        assert t.render(seq='ab') == 'TrueFalse'
-        t = env.from_string('{% for x in seq %}{% for y in seq %}'
-                            '{{ loop.first }}{% endfor %}{% endfor %}')
-        assert t.render(seq='ab') == 'TrueFalseTrueFalse'
-
-    def test_recursive_empty_loop_iter(self):
-        t = env.from_string('''
-        {%- for item in foo recursive -%}{%- endfor -%}
-        ''')
-        assert t.render(dict(foo=[])) == ''
-
-    def test_call_in_loop(self):
-        t = env.from_string('''
-        {%- macro do_something() -%}
-            [{{ caller() }}]
-        {%- endmacro %}
-
-        {%- for i in [1, 2, 3] %}
-            {%- call do_something() -%}
-                {{ i }}
-            {%- endcall %}
-        {%- endfor -%}
-        ''')
-        assert t.render() == '[1][2][3]'
-
-    def test_scoping_bug(self):
-        t = env.from_string('''
-        {%- for item in foo %}...{{ item }}...{% endfor %}
-        {%- macro item(a) %}...{{ a }}...{% endmacro %}
-        {{- item(2) -}}
-        ''')
-        assert t.render(foo=(1,)) == '...1......2...'
-
-    def test_unpacking(self):
-        tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
-            '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
-        assert tmpl.render() == '1|2|3'
-
-
-class IfConditionTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        tmpl = env.from_string('''{% if true %}...{% endif %}''')
-        assert tmpl.render() == '...'
-
-    def test_elif(self):
-        tmpl = env.from_string('''{% if false %}XXX{% elif true
-            %}...{% else %}XXX{% endif %}''')
-        assert tmpl.render() == '...'
-
-    def test_else(self):
-        tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
-        assert tmpl.render() == '...'
-
-    def test_empty(self):
-        tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
-        assert tmpl.render() == '[]'
-
-    def test_complete(self):
-        tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
-                               'C{% else %}D{% endif %}')
-        assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
-
-    def test_no_scope(self):
-        tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
-        assert tmpl.render(a=True) == '1'
-        tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
-        assert tmpl.render() == '1'
-
-
-class MacrosTestCase(JinjaTestCase):
-    env = Environment(trim_blocks=True)
-
-    def test_simple(self):
-        tmpl = self.env.from_string('''\
-{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
-{{ say_hello('Peter') }}''')
-        assert tmpl.render() == 'Hello Peter!'
-
-    def test_scoping(self):
-        tmpl = self.env.from_string('''\
-{% macro level1(data1) %}
-{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
-{{ level2('bar') }}{% endmacro %}
-{{ level1('foo') }}''')
-        assert tmpl.render() == 'foo|bar'
-
-    def test_arguments(self):
-        tmpl = self.env.from_string('''\
-{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
-{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
-        assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
-
-    def test_varargs(self):
-        tmpl = self.env.from_string('''\
-{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
-{{ test(1, 2, 3) }}''')
-        assert tmpl.render() == '1|2|3'
-
-    def test_simple_call(self):
-        tmpl = self.env.from_string('''\
-{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
-{% call test() %}data{% endcall %}''')
-        assert tmpl.render() == '[[data]]'
-
-    def test_complex_call(self):
-        tmpl = self.env.from_string('''\
-{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
-{% call(data) test() %}{{ data }}{% endcall %}''')
-        assert tmpl.render() == '[[data]]'
-
-    def test_caller_undefined(self):
-        tmpl = self.env.from_string('''\
-{% set caller = 42 %}\
-{% macro test() %}{{ caller is not defined }}{% endmacro %}\
-{{ test() }}''')
-        assert tmpl.render() == 'True'
-
-    def test_include(self):
-        self.env = Environment(loader=DictLoader({'include':
-            '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
-        tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
-        assert tmpl.render() == '[foo]'
-
-    def test_macro_api(self):
-        tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
-                               '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
-                               '{% macro baz() %}{{ caller() }}{% endmacro %}')
-        assert tmpl.module.foo.arguments == ('a', 'b')
-        assert tmpl.module.foo.defaults == ()
-        assert tmpl.module.foo.name == 'foo'
-        assert not tmpl.module.foo.caller
-        assert not tmpl.module.foo.catch_kwargs
-        assert not tmpl.module.foo.catch_varargs
-        assert tmpl.module.bar.arguments == ()
-        assert tmpl.module.bar.defaults == ()
-        assert not tmpl.module.bar.caller
-        assert tmpl.module.bar.catch_kwargs
-        assert tmpl.module.bar.catch_varargs
-        assert tmpl.module.baz.caller
-
-    def test_callself(self):
-        tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
-                                    '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
-                                    '{{ foo(5) }}')
-        assert tmpl.render() == '5|4|3|2|1'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ForLoopTestCase))
-    suite.addTest(unittest.makeSuite(IfConditionTestCase))
-    suite.addTest(unittest.makeSuite(MacrosTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py
deleted file mode 100644
index 55be94a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.debug
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests the debug system.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import sys
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase, filesystem_loader
-
-from ambari_jinja2 import Environment, TemplateSyntaxError
-
-env = Environment(loader=filesystem_loader)
-
-
-class DebugTestCase(JinjaTestCase):
-
-    if sys.version_info[:2] != (2, 4):
-        def test_runtime_error(self):
-            def test():
-                tmpl.render(fail=lambda: 1 / 0)
-            tmpl = env.get_template('broken.html')
-            self.assert_traceback_matches(test, r'''
-  File ".*?broken.html", line 2, in (top-level template code|<module>)
-    \{\{ fail\(\) \}\}
-  File ".*?debug.pyc?", line \d+, in <lambda>
-    tmpl\.render\(fail=lambda: 1 / 0\)
-ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
-''')
-
-    def test_syntax_error(self):
-        # XXX: the .*? is necessary for python3 which does not hide
-        # some of the stack frames we don't want to show.  Not sure
-        # what's up with that, but that is not that critical.  Should
-        # be fixed though.
-        self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
-  File ".*?syntaxerror.html", line 4, in (template|<module>)
-    \{% endif %\}.*?
-(ambari_jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
-    ''')
-
-    def test_regular_syntax_error(self):
-        def test():
-            raise TemplateSyntaxError('wtf', 42)
-        self.assert_traceback_matches(test, r'''
-  File ".*debug.pyc?", line \d+, in test
-    raise TemplateSyntaxError\('wtf', 42\)
-(ambari_jinja2\.exceptions\.)?TemplateSyntaxError: wtf
-  line 42''')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(DebugTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py
deleted file mode 100644
index 72ddde5..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.doctests
-    ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    The doctests.  Collects all tests we want to test from
-    the Jinja modules.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-import doctest
-
-
-def suite():
-    from ambari_jinja2 import utils, sandbox, runtime, meta, loaders, \
-        ext, environment, bccache, nodes
-    suite = unittest.TestSuite()
-    suite.addTest(doctest.DocTestSuite(utils))
-    suite.addTest(doctest.DocTestSuite(sandbox))
-    suite.addTest(doctest.DocTestSuite(runtime))
-    suite.addTest(doctest.DocTestSuite(meta))
-    suite.addTest(doctest.DocTestSuite(loaders))
-    suite.addTest(doctest.DocTestSuite(ext))
-    suite.addTest(doctest.DocTestSuite(environment))
-    suite.addTest(doctest.DocTestSuite(bccache))
-    suite.addTest(doctest.DocTestSuite(nodes))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py
deleted file mode 100644
index 8a9a8d9..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py
+++ /dev/null
@@ -1,455 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.ext
-    ~~~~~~~~~~~~~~~~~~~~
-
-    Tests for the extensions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase, filesystem_loader
-
-from ambari_jinja2 import Environment, DictLoader, contextfunction, nodes
-from ambari_jinja2.exceptions import TemplateAssertionError
-from ambari_jinja2.ext import Extension
-from ambari_jinja2.lexer import Token, count_newlines
-from ambari_jinja2.utils import next
-
-# 2.x / 3.x
-try:
-    from io import BytesIO
-except ImportError:
-    from StringIO import StringIO as BytesIO
-
-
-importable_object = 23
-
-_gettext_re = re.compile(r'_\((.*?)\)(?s)')
-
-
-i18n_templates = {
-    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
-                   '{% block body %}{% endblock %}',
-    'child.html': '{% extends "master.html" %}{% block body %}'
-                  '{% trans %}watch out{% endtrans %}{% endblock %}',
-    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
-                   '{{ user_count }} users online{% endtrans %}',
-    'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}'
-}
-
-newstyle_i18n_templates = {
-    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
-                   '{% block body %}{% endblock %}',
-    'child.html': '{% extends "master.html" %}{% block body %}'
-                  '{% trans %}watch out{% endtrans %}{% endblock %}',
-    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
-                   '{{ user_count }} users online{% endtrans %}',
-    'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}',
-    'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}',
-    'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}'
-                          '{{ num }} apples{% endtrans %}',
-    'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}',
-    'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}',
-    'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}',
-    'novars.html': '{% trans %}%(hello)s{% endtrans %}',
-    'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}',
-    'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}'
-}
-
-
-languages = {
-    'de': {
-        'missing':                      u'fehlend',
-        'watch out':                    u'pass auf',
-        'One user online':              u'Ein Benutzer online',
-        '%(user_count)s users online':  u'%(user_count)s Benutzer online',
-        'User: %(num)s':                u'Benutzer: %(num)s',
-        'User: %(count)s':              u'Benutzer: %(count)s',
-        '%(num)s apple':                u'%(num)s Apfel',
-        '%(num)s apples':               u'%(num)s Äpfel'
-    }
-}
-
-
-@contextfunction
-def gettext(context, string):
-    language = context.get('LANGUAGE', 'en')
-    return languages.get(language, {}).get(string, string)
-
-
-@contextfunction
-def ngettext(context, s, p, n):
-    language = context.get('LANGUAGE', 'en')
-    if n != 1:
-        return languages.get(language, {}).get(p, p)
-    return languages.get(language, {}).get(s, s)
-
-
-i18n_env = Environment(
-    loader=DictLoader(i18n_templates),
-    extensions=['ambari_jinja2.ext.i18n']
-)
-i18n_env.globals.update({
-    '_':            gettext,
-    'gettext':      gettext,
-    'ngettext':     ngettext
-})
-
-newstyle_i18n_env = Environment(
-    loader=DictLoader(newstyle_i18n_templates),
-    extensions=['ambari_jinja2.ext.i18n']
-)
-newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
-
-class TestExtension(Extension):
-    tags = set(['test'])
-    ext_attr = 42
-
-    def parse(self, parser):
-        return nodes.Output([self.call_method('_dump', [
-            nodes.EnvironmentAttribute('sandboxed'),
-            self.attr('ext_attr'),
-            nodes.ImportedName(__name__ + '.importable_object'),
-            nodes.ContextReference()
-        ])]).set_lineno(next(parser.stream).lineno)
-
-    def _dump(self, sandboxed, ext_attr, imported_object, context):
-        return '%s|%s|%s|%s' % (
-            sandboxed,
-            ext_attr,
-            imported_object,
-            context.blocks
-        )
-
-
-class PreprocessorExtension(Extension):
-
-    def preprocess(self, source, name, filename=None):
-        return source.replace('[[TEST]]', '({{ foo }})')
-
-
-class StreamFilterExtension(Extension):
-
-    def filter_stream(self, stream):
-        for token in stream:
-            if token.type == 'data':
-                for t in self.interpolate(token):
-                    yield t
-            else:
-                yield token
-
-    def interpolate(self, token):
-        pos = 0
-        end = len(token.value)
-        lineno = token.lineno
-        while 1:
-            match = _gettext_re.search(token.value, pos)
-            if match is None:
-                break
-            value = token.value[pos:match.start()]
-            if value:
-                yield Token(lineno, 'data', value)
-            lineno += count_newlines(token.value)
-            yield Token(lineno, 'variable_begin', None)
-            yield Token(lineno, 'name', 'gettext')
-            yield Token(lineno, 'lparen', None)
-            yield Token(lineno, 'string', match.group(1))
-            yield Token(lineno, 'rparen', None)
-            yield Token(lineno, 'variable_end', None)
-            pos = match.end()
-        if pos < end:
-            yield Token(lineno, 'data', token.value[pos:])
-
-
-class ExtensionsTestCase(JinjaTestCase):
-
-    def test_extend_late(self):
-        env = Environment()
-        env.add_extension('ambari_jinja2.ext.autoescape')
-        t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
-        assert t.render() == '&lt;test&gt;'
-
-    def test_loop_controls(self):
-        env = Environment(extensions=['ambari_jinja2.ext.loopcontrols'])
-
-        tmpl = env.from_string('''
-            {%- for item in [1, 2, 3, 4] %}
-                {%- if item % 2 == 0 %}{% continue %}{% endif -%}
-                {{ item }}
-            {%- endfor %}''')
-        assert tmpl.render() == '13'
-
-        tmpl = env.from_string('''
-            {%- for item in [1, 2, 3, 4] %}
-                {%- if item > 2 %}{% break %}{% endif -%}
-                {{ item }}
-            {%- endfor %}''')
-        assert tmpl.render() == '12'
-
-    def test_do(self):
-        env = Environment(extensions=['ambari_jinja2.ext.do'])
-        tmpl = env.from_string('''
-            {%- set items = [] %}
-            {%- for char in "foo" %}
-                {%- do items.append(loop.index0 ~ char) %}
-            {%- endfor %}{{ items|join(', ') }}''')
-        assert tmpl.render() == '0f, 1o, 2o'
-
-    def test_with(self):
-        env = Environment(extensions=['ambari_jinja2.ext.with_'])
-        tmpl = env.from_string('''\
-        {% with a=42, b=23 -%}
-            {{ a }} = {{ b }}
-        {% endwith -%}
-            {{ a }} = {{ b }}\
-        ''')
-        assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
-            == ['42 = 23', '1 = 2']
-
-    def test_extension_nodes(self):
-        env = Environment(extensions=[TestExtension])
-        tmpl = env.from_string('{% test %}')
-        assert tmpl.render() == 'False|42|23|{}'
-
-    def test_identifier(self):
-        assert TestExtension.identifier == __name__ + '.TestExtension'
-
-    def test_rebinding(self):
-        original = Environment(extensions=[TestExtension])
-        overlay = original.overlay()
-        for env in original, overlay:
-            for ext in env.extensions.itervalues():
-                assert ext.environment is env
-
-    def test_preprocessor_extension(self):
-        env = Environment(extensions=[PreprocessorExtension])
-        tmpl = env.from_string('{[[TEST]]}')
-        assert tmpl.render(foo=42) == '{(42)}'
-
-    def test_streamfilter_extension(self):
-        env = Environment(extensions=[StreamFilterExtension])
-        env.globals['gettext'] = lambda x: x.upper()
-        tmpl = env.from_string('Foo _(bar) Baz')
-        out = tmpl.render()
-        assert out == 'Foo BAR Baz'
-
-    def test_extension_ordering(self):
-        class T1(Extension):
-            priority = 1
-        class T2(Extension):
-            priority = 2
-        env = Environment(extensions=[T1, T2])
-        ext = list(env.iter_extensions())
-        assert ext[0].__class__ is T1
-        assert ext[1].__class__ is T2
-
-
-class InternationalizationTestCase(JinjaTestCase):
-
-    def test_trans(self):
-        tmpl = i18n_env.get_template('child.html')
-        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
-
-    def test_trans_plural(self):
-        tmpl = i18n_env.get_template('plural.html')
-        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
-        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
-
-    def test_complex_plural(self):
-        tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
-                                    'pluralize count %}{{ count }} items{% endtrans %}')
-        assert tmpl.render() == '2 items'
-        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
-                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
-
-    def test_trans_stringformatting(self):
-        tmpl = i18n_env.get_template('stringformat.html')
-        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
-
-    def test_extract(self):
-        from ambari_jinja2.ext import babel_extract
-        source = BytesIO('''
-        {{ gettext('Hello World') }}
-        {% trans %}Hello World{% endtrans %}
-        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        '''.encode('ascii')) # make python 3 happy
-        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
-            (2, 'gettext', u'Hello World', []),
-            (3, 'gettext', u'Hello World', []),
-            (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
-        ]
-
-    def test_comment_extract(self):
-        from ambari_jinja2.ext import babel_extract
-        source = BytesIO('''
-        {# trans first #}
-        {{ gettext('Hello World') }}
-        {% trans %}Hello World{% endtrans %}{# trans second #}
-        {#: third #}
-        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        '''.encode('utf-8')) # make python 3 happy
-        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
-            (3, 'gettext', u'Hello World', ['first']),
-            (4, 'gettext', u'Hello World', ['second']),
-            (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
-        ]
-
-
-class NewstyleInternationalizationTestCase(JinjaTestCase):
-
-    def test_trans(self):
-        tmpl = newstyle_i18n_env.get_template('child.html')
-        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
-
-    def test_trans_plural(self):
-        tmpl = newstyle_i18n_env.get_template('plural.html')
-        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
-        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
-
-    def test_complex_plural(self):
-        tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
-                                    'pluralize count %}{{ count }} items{% endtrans %}')
-        assert tmpl.render() == '2 items'
-        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
-                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
-
-    def test_trans_stringformatting(self):
-        tmpl = newstyle_i18n_env.get_template('stringformat.html')
-        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
-
-    def test_newstyle_plural(self):
-        tmpl = newstyle_i18n_env.get_template('ngettext.html')
-        assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel'
-        assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel'
-
-    def test_autoescape_support(self):
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape',
-                                      'ambari_jinja2.ext.i18n'])
-        env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
-                                      lambda s, p, n: s, newstyle=True)
-        t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
-                            '"<test>") }}{% endautoescape %}')
-        assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
-        assert t.render(ae=False) == '<strong>Wert: <test></strong>'
-
-    def test_num_used_twice(self):
-        tmpl = newstyle_i18n_env.get_template('ngettext_long.html')
-        assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Äpfel'
-
-    def test_num_called_num(self):
-        source = newstyle_i18n_env.compile('''
-            {% trans num=3 %}{{ num }} apple{% pluralize
-            %}{{ num }} apples{% endtrans %}
-        ''', raw=True)
-        # quite hacky, but the only way to properly test that.  The idea is
-        # that the generated code does not pass num twice (although that
-        # would work) for better performance.  This only works on the
-        # newstyle gettext of course
-        assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s "
-                         r"apples', 3", source) is not None
-
-    def test_trans_vars(self):
-        t1 = newstyle_i18n_env.get_template('transvars1.html')
-        t2 = newstyle_i18n_env.get_template('transvars2.html')
-        t3 = newstyle_i18n_env.get_template('transvars3.html')
-        assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1'
-        assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23'
-        assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42'
-
-    def test_novars_vars_escaping(self):
-        t = newstyle_i18n_env.get_template('novars.html')
-        assert t.render() == '%(hello)s'
-        t = newstyle_i18n_env.get_template('vars.html')
-        assert t.render(foo='42') == '42%(foo)s'
-        t = newstyle_i18n_env.get_template('explicitvars.html')
-        assert t.render() == '%(foo)s'
-
-
-class AutoEscapeTestCase(JinjaTestCase):
-
-    def test_scoped_setting(self):
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
-                          autoescape=True)
-        tmpl = env.from_string('''
-            {{ "<HelloWorld>" }}
-            {% autoescape false %}
-                {{ "<HelloWorld>" }}
-            {% endautoescape %}
-            {{ "<HelloWorld>" }}
-        ''')
-        assert tmpl.render().split() == \
-            [u'&lt;HelloWorld&gt;', u'<HelloWorld>', u'&lt;HelloWorld&gt;']
-
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
-                          autoescape=False)
-        tmpl = env.from_string('''
-            {{ "<HelloWorld>" }}
-            {% autoescape true %}
-                {{ "<HelloWorld>" }}
-            {% endautoescape %}
-            {{ "<HelloWorld>" }}
-        ''')
-        assert tmpl.render().split() == \
-            [u'<HelloWorld>', u'&lt;HelloWorld&gt;', u'<HelloWorld>']
-
-    def test_nonvolatile(self):
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
-                          autoescape=True)
-        tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}')
-        assert tmpl.render() == ' foo="&lt;test&gt;"'
-        tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}'
-                               '|xmlattr|escape }}{% endautoescape %}')
-        assert tmpl.render() == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
-
-    def test_volatile(self):
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
-                          autoescape=True)
-        tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}'
-                               '|xmlattr|escape }}{% endautoescape %}')
-        assert tmpl.render(foo=False) == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
-        assert tmpl.render(foo=True) == ' foo="&lt;test&gt;"'
-
-    def test_scoping(self):
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'])
-        tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
-                               '{% endautoescape %}{{ x }}{{ "<y>" }}')
-        assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
-
-    def test_volatile_scoping(self):
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'])
-        tmplsource = '''
-        {% autoescape val %}
-            {% macro foo(x) %}
-                [{{ x }}]
-            {% endmacro %}
-            {{ foo().__class__.__name__ }}
-        {% endautoescape %}
-        {{ '<testing>' }}
-        '''
-        tmpl = env.from_string(tmplsource)
-        assert tmpl.render(val=True).split()[0] == 'Markup'
-        assert tmpl.render(val=False).split()[0] == unicode.__name__
-
-        # looking at the source we should see <testing> there in raw
-        # (and then escaped as well)
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'])
-        pysource = env.compile(tmplsource, raw=True)
-        assert '<testing>\\n' in pysource
-
-        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
-                          autoescape=True)
-        pysource = env.compile(tmplsource, raw=True)
-        assert '&lt;testing&gt;\\n' in pysource
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ExtensionsTestCase))
-    suite.addTest(unittest.makeSuite(InternationalizationTestCase))
-    suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
-    suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py
deleted file mode 100644
index 9d0b098..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.filters
-    ~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests for the jinja filters.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Markup, Environment
-
-env = Environment()
-
-
-class FilterTestCase(JinjaTestCase):
-
-    def test_capitalize(self):
-        tmpl = env.from_string('{{ "foo bar"|capitalize }}')
-        assert tmpl.render() == 'Foo bar'
-
-    def test_center(self):
-        tmpl = env.from_string('{{ "foo"|center(9) }}')
-        assert tmpl.render() == '   foo   '
-
-    def test_default(self):
-        tmpl = env.from_string(
-            "{{ missing|default('no') }}|{{ false|default('no') }}|"
-            "{{ false|default('no', true) }}|{{ given|default('no') }}"
-        )
-        assert tmpl.render(given='yes') == 'no|False|no|yes'
-
-    def test_dictsort(self):
-        tmpl = env.from_string(
-            '{{ foo|dictsort }}|'
-            '{{ foo|dictsort(true) }}|'
-            '{{ foo|dictsort(false, "value") }}'
-        )
-        out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
-        assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
-                       "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
-                       "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
-
-    def test_batch(self):
-        tmpl = env.from_string("{{ foo|batch(3)|list }}|"
-                               "{{ foo|batch(3, 'X')|list }}")
-        out = tmpl.render(foo=range(10))
-        assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
-                       "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
-
-    def test_slice(self):
-        tmpl = env.from_string('{{ foo|slice(3)|list }}|'
-                               '{{ foo|slice(3, "X")|list }}')
-        out = tmpl.render(foo=range(10))
-        assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
-                       "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
-
-    def test_escape(self):
-        tmpl = env.from_string('''{{ '<">&'|escape }}''')
-        out = tmpl.render()
-        assert out == '&lt;&#34;&gt;&amp;'
-
-    def test_striptags(self):
-        tmpl = env.from_string('''{{ foo|striptags }}''')
-        out = tmpl.render(foo='  <p>just a small   \n <a href="#">'
-                          'example</a> link</p>\n<p>to a webpage</p> '
-                          '<!-- <p>and some commented stuff</p> -->')
-        assert out == 'just a small example link to a webpage'
-
-    def test_filesizeformat(self):
-        tmpl = env.from_string(
-            '{{ 100|filesizeformat }}|'
-            '{{ 1000|filesizeformat }}|'
-            '{{ 1000000|filesizeformat }}|'
-            '{{ 1000000000|filesizeformat }}|'
-            '{{ 1000000000000|filesizeformat }}|'
-            '{{ 100|filesizeformat(true) }}|'
-            '{{ 1000|filesizeformat(true) }}|'
-            '{{ 1000000|filesizeformat(true) }}|'
-            '{{ 1000000000|filesizeformat(true) }}|'
-            '{{ 1000000000000|filesizeformat(true) }}'
-        )
-        out = tmpl.render()
-        assert out == (
-            '100 Bytes|1.0 KB|1.0 MB|1.0 GB|1000.0 GB|'
-            '100 Bytes|1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
-        )
-
-    def test_first(self):
-        tmpl = env.from_string('{{ foo|first }}')
-        out = tmpl.render(foo=range(10))
-        assert out == '0'
-
-    def test_float(self):
-        tmpl = env.from_string('{{ "42"|float }}|'
-                               '{{ "ajsghasjgd"|float }}|'
-                               '{{ "32.32"|float }}')
-        out = tmpl.render()
-        assert out == '42.0|0.0|32.32'
-
-    def test_format(self):
-        tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
-        out = tmpl.render()
-        assert out == 'a|b'
-
-    def test_indent(self):
-        tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
-        text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
-        out = tmpl.render(foo=text)
-        assert out == ('foo bar foo bar\n  foo bar foo bar|  '
-                       'foo bar foo bar\n  foo bar foo bar')
-
-    def test_int(self):
-        tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
-                               '{{ "32.32"|int }}')
-        out = tmpl.render()
-        assert out == '42|0|32'
-
-    def test_join(self):
-        tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
-        out = tmpl.render()
-        assert out == '1|2|3'
-
-        env2 = Environment(autoescape=True)
-        tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
-        assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
-
-    def test_last(self):
-        tmpl = env.from_string('''{{ foo|last }}''')
-        out = tmpl.render(foo=range(10))
-        assert out == '9'
-
-    def test_length(self):
-        tmpl = env.from_string('''{{ "hello world"|length }}''')
-        out = tmpl.render()
-        assert out == '11'
-
-    def test_lower(self):
-        tmpl = env.from_string('''{{ "FOO"|lower }}''')
-        out = tmpl.render()
-        assert out == 'foo'
-
-    def test_pprint(self):
-        from pprint import pformat
-        tmpl = env.from_string('''{{ data|pprint }}''')
-        data = range(1000)
-        assert tmpl.render(data=data) == pformat(data)
-
-    def test_random(self):
-        tmpl = env.from_string('''{{ seq|random }}''')
-        seq = range(100)
-        for _ in range(10):
-            assert int(tmpl.render(seq=seq)) in seq
-
-    def test_reverse(self):
-        tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
-                               '{{ [1, 2, 3]|reverse|list }}')
-        assert tmpl.render() == 'raboof|[3, 2, 1]'
-
-    def test_string(self):
-        x = [1, 2, 3, 4, 5]
-        tmpl = env.from_string('''{{ obj|string }}''')
-        assert tmpl.render(obj=x) == unicode(x)
-
-    def test_title(self):
-        tmpl = env.from_string('''{{ "foo bar"|title }}''')
-        assert tmpl.render() == "Foo Bar"
-
-    def test_truncate(self):
-        tmpl = env.from_string(
-            '{{ data|truncate(15, true, ">>>") }}|'
-            '{{ data|truncate(15, false, ">>>") }}|'
-            '{{ smalldata|truncate(15) }}'
-        )
-        out = tmpl.render(data='foobar baz bar' * 1000,
-                          smalldata='foobar baz bar')
-        assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar'
-
-    def test_upper(self):
-        tmpl = env.from_string('{{ "foo"|upper }}')
-        assert tmpl.render() == 'FOO'
-
-    def test_urlize(self):
-        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
-        assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
-                                'http://www.example.com/</a> bar'
-
-    def test_wordcount(self):
-        tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
-        assert tmpl.render() == '3'
-
-    def test_block(self):
-        tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
-        assert tmpl.render() == '&lt;hehe&gt;'
-
-    def test_chaining(self):
-        tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
-        assert tmpl.render() == '&lt;FOO&gt;'
-
-    def test_sum(self):
-        tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
-        assert tmpl.render() == '21'
-
-    def test_abs(self):
-        tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
-        assert tmpl.render() == '1|1', tmpl.render()
-
-    def test_round_positive(self):
-        tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
-                               "{{ 2.1234|round(3, 'floor') }}|"
-                               "{{ 2.1|round(0, 'ceil') }}")
-        assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
-
-    def test_round_negative(self):
-        tmpl = env.from_string('{{ 21.3|round(-1)}}|'
-                               "{{ 21.3|round(-1, 'ceil')}}|"
-                               "{{ 21.3|round(-1, 'floor')}}")
-        assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
-
-    def test_xmlattr(self):
-        tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
-                               "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
-        out = tmpl.render().split()
-        assert len(out) == 3
-        assert 'foo="42"' in out
-        assert 'bar="23"' in out
-        assert 'blub:blub="&lt;?&gt;"' in out
-
-    def test_sort1(self):
-        tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
-        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
-
-    def test_sort2(self):
-        tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort(false, true)) }}')
-        assert tmpl.render() == 'AbcD'
-
-    def test_groupby(self):
-        tmpl = env.from_string('''
-        {%- for grouper, list in [{'foo': 1, 'bar': 2},
-                                  {'foo': 2, 'bar': 3},
-                                  {'foo': 1, 'bar': 1},
-                                  {'foo': 3, 'bar': 4}]|groupby('foo') -%}
-            {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
-        {%- endfor %}''')
-        assert tmpl.render().split('|') == [
-            "1: 1, 2: 1, 1",
-            "2: 2, 3",
-            "3: 3, 4",
-            ""
-        ]
-
-    def test_filtertag(self):
-        tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
-                               "foobar{% endfilter %}")
-        assert tmpl.render() == 'fooBAR'
-
-    def test_replace(self):
-        env = Environment()
-        tmpl = env.from_string('{{ string|replace("o", 42) }}')
-        assert tmpl.render(string='<foo>') == '<f4242>'
-        env = Environment(autoescape=True)
-        tmpl = env.from_string('{{ string|replace("o", 42) }}')
-        assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
-        tmpl = env.from_string('{{ string|replace("<", 42) }}')
-        assert tmpl.render(string='<foo>') == '42foo&gt;'
-        tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
-        assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
-
-    def test_forceescape(self):
-        tmpl = env.from_string('{{ x|forceescape }}')
-        assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
-
-    def test_safe(self):
-        env = Environment(autoescape=True)
-        tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
-        assert tmpl.render() == '<div>foo</div>'
-        tmpl = env.from_string('{{ "<div>foo</div>" }}')
-        assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
-
-    def test_sort2(self):
-        tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
-        assert tmpl.render() == "['Bar', 'blah', 'foo']"
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(FilterTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py
deleted file mode 100644
index 799daf1..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.imports
-    ~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests the import features (with includes).
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment, DictLoader
-from ambari_jinja2.exceptions import TemplateNotFound, TemplatesNotFound
-
-
-test_env = Environment(loader=DictLoader(dict(
-    module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
-    header='[{{ foo }}|{{ 23 }}]',
-    o_printer='({{ o }})'
-)))
-test_env.globals['bar'] = 23
-
-
-class ImportsTestCase(JinjaTestCase):
-
-    def test_context_imports(self):
-        t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
-        assert t.render(foo=42) == '[42|23]'
-        t = test_env.from_string('{% from "module" import test %}{{ test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
-        assert t.render(foo=42) == '[42|23]'
-
-    def test_trailing_comma(self):
-        test_env.from_string('{% from "foo" import bar, baz with context %}')
-        test_env.from_string('{% from "foo" import bar, baz, with context %}')
-        test_env.from_string('{% from "foo" import bar, with context %}')
-        test_env.from_string('{% from "foo" import bar, with, context %}')
-        test_env.from_string('{% from "foo" import bar, with with context %}')
-
-    def test_exports(self):
-        m = test_env.from_string('''
-            {% macro toplevel() %}...{% endmacro %}
-            {% macro __private() %}...{% endmacro %}
-            {% set variable = 42 %}
-            {% for item in [1] %}
-                {% macro notthere() %}{% endmacro %}
-            {% endfor %}
-        ''').module
-        assert m.toplevel() == '...'
-        assert not hasattr(m, '__missing')
-        assert m.variable == 42
-        assert not hasattr(m, 'notthere')
-
-
-class IncludesTestCase(JinjaTestCase):
-
-    def test_context_include(self):
-        t = test_env.from_string('{% include "header" %}')
-        assert t.render(foo=42) == '[42|23]'
-        t = test_env.from_string('{% include "header" with context %}')
-        assert t.render(foo=42) == '[42|23]'
-        t = test_env.from_string('{% include "header" without context %}')
-        assert t.render(foo=42) == '[|23]'
-
-    def test_choice_includes(self):
-        t = test_env.from_string('{% include ["missing", "header"] %}')
-        assert t.render(foo=42) == '[42|23]'
-
-        t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
-        assert t.render(foo=42) == ''
-
-        t = test_env.from_string('{% include ["missing", "missing2"] %}')
-        self.assert_raises(TemplateNotFound, t.render)
-        try:
-            t.render()
-        except TemplatesNotFound, e:
-            assert e.templates == ['missing', 'missing2']
-            assert e.name == 'missing2'
-        else:
-            assert False, 'thou shalt raise'
-
-        def test_includes(t, **ctx):
-            ctx['foo'] = 42
-            assert t.render(ctx) == '[42|23]'
-
-        t = test_env.from_string('{% include ["missing", "header"] %}')
-        test_includes(t)
-        t = test_env.from_string('{% include x %}')
-        test_includes(t, x=['missing', 'header'])
-        t = test_env.from_string('{% include [x, "header"] %}')
-        test_includes(t, x='missing')
-        t = test_env.from_string('{% include x %}')
-        test_includes(t, x='header')
-        t = test_env.from_string('{% include x %}')
-        test_includes(t, x='header')
-        t = test_env.from_string('{% include [x] %}')
-        test_includes(t, x='header')
-
-    def test_include_ignoring_missing(self):
-        t = test_env.from_string('{% include "missing" %}')
-        self.assert_raises(TemplateNotFound, t.render)
-        for extra in '', 'with context', 'without context':
-            t = test_env.from_string('{% include "missing" ignore missing ' +
-                                     extra + ' %}')
-            assert t.render() == ''
-
-    def test_context_include_with_overrides(self):
-        env = Environment(loader=DictLoader(dict(
-            main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
-            item="{{ item }}"
-        )))
-        assert env.get_template("main").render() == "123"
-
-    def test_unoptimized_scopes(self):
-        t = test_env.from_string("""
-            {% macro outer(o) %}
-            {% macro inner() %}
-            {% include "o_printer" %}
-            {% endmacro %}
-            {{ inner() }}
-            {% endmacro %}
-            {{ outer("FOO") }}
-        """)
-        assert t.render().strip() == '(FOO)'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ImportsTestCase))
-    suite.addTest(unittest.makeSuite(IncludesTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py
deleted file mode 100644
index e0666e5..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.testsuite.inheritance
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests the template inheritance feature.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from ambari_jinja2.testsuite import JinjaTestCase
-
-from ambari_jinja2 import Environment, DictLoader
-from ambari_jinja2.exceptions import TemplateSyntaxError
-
-
-LAYOUTTEMPLATE = '''\
-|{% block block1 %}block 1 from layout{% endblock %}
-|{% block block2 %}block 2 from layout{% endblock %}
-|{% block block3 %}
-{% block block4 %}nested block 4 from layout{% endblock %}
-{% endblock %}|'''
-
-LEVEL1TEMPLATE = '''\
-{% extends "layout" %}
-{% block block1 %}block 1 from level1{% endblock %}'''
-
-LEVEL2TEMPLATE = '''\
-{% extends "level1" %}
-{% block block2 %}{% block block5 %}nested block 5 from level2{%
-endblock %}{% endblock %}'''
-
-LEVEL3TEMPLATE = '''\
-{% extends "level2" %}
-{% block block5 %}block 5 from level3{% endblock %}
-{% block block4 %}block 4 from level3{% endblock %}
-'''
-
-LEVEL4TEMPLATE = '''\
-{% extends "level3" %}
-{% block block3 %}block 3 from level4{% endblock %}
-'''
-
-WORKINGTEMPLATE = '''\
-{% extends "layout" %}
-{% block block1 %}
-  {% if false %}
-    {% block block2 %}
-      this should workd
-    {% endblock %}
-  {% endif %}
-{% endblock %}
-'''
-
-env = Environment(loader=DictLoader({
-    'layout':       LAYOUTTEMPLATE,
-    'level1':       LEVEL1TEMPLATE,
-    'level2':       LEVEL2TEMPLATE,
-    'level3':       LEVEL3TEMPLATE,
-    'level4':       LEVEL4TEMPLATE,
-    'working':      WORKINGTEMPLATE
-}), trim_blocks=True)
-
-
-class InheritanceTestCase(JinjaTestCase):
-
-    def test_layout(self):
-        tmpl = env.get_template('layout')
-        assert tmpl.render() == ('|block 1 from layout|block 2 from '
-                                 'layout|nested block 4 from layout|')
-
-    def test_level1(self):
-        tmpl = env.get_template('level1')
-        assert tmpl.render() == ('|block 1 from level1|block 2 from '
-                                 'layout|nested block 4 from layout|')
-
-    def test_level2(self):
-        tmpl = env.get_template('level2')
-        assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
-                                 'level2|nested block 4 from layout|')
-
-    def test_level3(self):
-        tmpl = env.get_template('level3')
-        assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
-                                 'block 4 from level3|')
-
-    def test_level4(sel):
-        tmpl = env.get_template('level4')
-        assert tmpl.render() == ('|block 1 from level1|block 5 from '
-                                 'level3|block 3 from level4|')
-
-    def test_super(self):
-        env = Environment(loader=DictLoader({
-            'a': '{% block intro %}INTRO{% endblock %}|'
-                 'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
-            'b': '{% extends "a" %}{% block data %}({{ '
-                 'super() }}){% endblock %}',
-            'c': '{% extends "b" %}{% block intro %}--{{ '
-                 'super() }}--{% endblock %}\n{% block data '
-                 '%}[{{ super() }}]{% endblock %}'
-        }))
-        tmpl = env.get_template('c')
-        assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
-
-    def test_working(self):
-        tmpl = env.get_template('working')
-
-    def test_reuse_blocks(self):
-        tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
-                               '{% endblock %}|{{ self.foo() }}')
-        assert tmpl.render() == '42|42|42'
-
-    def test_preserve_blocks(self):
-        env = Environment(loader=DictLoader({
-            'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
-            'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
-        }))
-        tmpl = env.get_template('b')
-        assert tmpl.render() == 'BA'
-
-    def test_dynamic_inheritance(self):
-        env = Environment(loader=DictLoader({
-            'master1': 'MASTER1{% block x %}{% endblock %}',
-            'master2': 'MASTER2{% block x %}{% endblock %}',
-            'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
-        }))
-        tmpl = env.get_template('child')
-        for m in range(1, 3):
-            assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
-
-    def test_multi_inheritance(self):
-        env = Environment(loader=DictLoader({
-            'master1': 'MASTER1{% block x %}{% endblock %}',
-            'master2': 'MASTER2{% block x %}{% endblock %}',
-            'child': '''{% if master %}{% extends master %}{% else %}{% extends
-                        'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
-        }))
-        tmpl = env.get_template('child')
-        assert tmpl.render(master='master2') == 'MASTER2CHILD'
-        assert tmpl.render(master='master1') == 'MASTER1CHILD'
-        assert tmpl.render() == 'MASTER1CHILD'
-
-    def test_scoped_block(self):
-        env = Environment(loader=DictLoader({
-            'master.html': '{% for item in seq %}[{% block item scoped %}'
-                           '{% endblock %}]{% endfor %}'
-        }))
-        t = env.from_string('{% extends "master.html" %}{% block item %}'
-                            '{{ item }}{% endblock %}')
-        assert t.render(seq=range(5)) == '[0][1][2][3][4]'
-
-    def test_super_in_scoped_block(self):
-        env = Environment(loader=DictLoader({
-            'master.html': '{% for item in seq %}[{% block item scoped %}'
-                           '{{ item }}{% endblock %}]{% endfor %}'
-        }))
-        t = env.from_string('{% extends "master.html" %}{% block item %}'
-                            '{{ super() }}|{{ item * 2 }}{% endblock %}')
-        assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]'
-
-
-class BugFixTestCase(JinjaTestCase):
-
-    def test_fixed_macro_scoping_bug(self):
-        assert Environment(loader=DictLoader({
-            'test.html': '''\
-        {% extends 'details.html' %}
-
-        {% macro my_macro() %}
-        my_macro
-        {% endmacro %}
-
-        {% block inner_box %}
-            {{ my_macro() }}
-        {% endblock %}
-            ''',
-            'details.html': '''\
-        {% extends 'standard.html' %}
-
-        {% macro my_macro() %}
-        my_macro
-        {% endmacro %}
-
-        {% block content %}
-            {% block outer_box %}
-                outer_box
-                {% block inner_box %}
-                    inner_box
-                {% endblock %}
-            {% endblock %}
-        {% endblock %}
-        ''',
-            'standard.html': '''
-        {% block content %}&nbsp;{% endblock %}
-        '''
-        })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(InheritanceTestCase))
-    suite.addTest(unittest.makeSuite(BugFixTestCase))
-    return suite


[30/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py
deleted file mode 100644
index 008a0a9..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/lexnparse.py
+++ /dev/null
@@ -1,390 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.lexnparse
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    All the unittests regarding lexing, parsing and syntax.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import time
-import tempfile
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment, Template, TemplateSyntaxError, \
-     UndefinedError, nodes
-
-env = Environment()
-
-
-# how does a string look like in jinja syntax?
-if sys.version_info < (3, 0):
-    def jinja_string_repr(string):
-        return repr(string)[1:]
-else:
-    jinja_string_repr = repr
-
-
-class LexerTestCase(JinjaTestCase):
-
-    def test_raw1(self):
-        tmpl = env.from_string('{% raw %}foo{% endraw %}|'
-                               '{%raw%}{{ bar }}|{% baz %}{%       endraw    %}')
-        assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
-
-    def test_raw2(self):
-        tmpl = env.from_string('1  {%- raw -%}   2   {%- endraw -%}   3')
-        assert tmpl.render() == '123'
-
-    def test_balancing(self):
-        env = Environment('{%', '%}', '${', '}')
-        tmpl = env.from_string('''{% for item in seq
-            %}${{'foo': item}|upper}{% endfor %}''')
-        assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
-
-    def test_comments(self):
-        env = Environment('<!--', '-->', '{', '}')
-        tmpl = env.from_string('''\
-<ul>
-<!--- for item in seq -->
-  <li>{item}</li>
-<!--- endfor -->
-</ul>''')
-        assert tmpl.render(seq=range(3)) == ("<ul>\n  <li>0</li>\n  "
-                                             "<li>1</li>\n  <li>2</li>\n</ul>")
-
-    def test_string_escapes(self):
-        for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
-            tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
-            assert tmpl.render() == char
-        assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
-
-    def test_bytefallback(self):
-        from pprint import pformat
-        tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
-        assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
-
-    def test_operators(self):
-        from jinja2.lexer import operators
-        for test, expect in operators.iteritems():
-            if test in '([{}])':
-                continue
-            stream = env.lexer.tokenize('{{ %s }}' % test)
-            stream.next()
-            assert stream.current.type == expect
-
-    def test_normalizing(self):
-        for seq in '\r', '\r\n', '\n':
-            env = Environment(newline_sequence=seq)
-            tmpl = env.from_string('1\n2\r\n3\n4\n')
-            result = tmpl.render()
-            assert result.replace(seq, 'X') == '1X2X3X4'
-
-
-class ParserTestCase(JinjaTestCase):
-
-    def test_php_syntax(self):
-        env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
-        tmpl = env.from_string('''\
-<!-- I'm a comment, I'm not interesting -->\
-<? for item in seq -?>
-    <?= item ?>
-<?- endfor ?>''')
-        assert tmpl.render(seq=range(5)) == '01234'
-
-    def test_erb_syntax(self):
-        env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
-        tmpl = env.from_string('''\
-<%# I'm a comment, I'm not interesting %>\
-<% for item in seq -%>
-    <%= item %>
-<%- endfor %>''')
-        assert tmpl.render(seq=range(5)) == '01234'
-
-    def test_comment_syntax(self):
-        env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
-        tmpl = env.from_string('''\
-<!--# I'm a comment, I'm not interesting -->\
-<!-- for item in seq --->
-    ${item}
-<!--- endfor -->''')
-        assert tmpl.render(seq=range(5)) == '01234'
-
-    def test_balancing(self):
-        tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
-        assert tmpl.render() == 'bar'
-
-    def test_start_comment(self):
-        tmpl = env.from_string('''{# foo comment
-and bar comment #}
-{% macro blub() %}foo{% endmacro %}
-{{ blub() }}''')
-        assert tmpl.render().strip() == 'foo'
-
-    def test_line_syntax(self):
-        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
-        tmpl = env.from_string('''\
-<%# regular comment %>
-% for item in seq:
-    ${item}
-% endfor''')
-        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
-               range(5)
-
-        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
-        tmpl = env.from_string('''\
-<%# regular comment %>
-% for item in seq:
-    ${item} ## the rest of the stuff
-% endfor''')
-        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
-                range(5)
-
-    def test_line_syntax_priority(self):
-        # XXX: why is the whitespace there in front of the newline?
-        env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
-        tmpl = env.from_string('''\
-/* ignore me.
-   I'm a multiline comment */
-## for item in seq:
-* ${item}          # this is just extra stuff
-## endfor''')
-        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2'
-        env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##')
-        tmpl = env.from_string('''\
-/* ignore me.
-   I'm a multiline comment */
-# for item in seq:
-* ${item}          ## this is just extra stuff
-    ## extra stuff i just want to ignore
-# endfor''')
-        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
-
-    def test_error_messages(self):
-        def assert_error(code, expected):
-            try:
-                Template(code)
-            except TemplateSyntaxError, e:
-                assert str(e) == expected, 'unexpected error message'
-            else:
-                assert False, 'that was suposed to be an error'
-
-        assert_error('{% for item in seq %}...{% endif %}',
-                     "Encountered unknown tag 'endif'. Jinja was looking "
-                     "for the following tags: 'endfor' or 'else'. The "
-                     "innermost block that needs to be closed is 'for'.")
-        assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
-                     "Encountered unknown tag 'endfor'. Jinja was looking for "
-                     "the following tags: 'elif' or 'else' or 'endif'. The "
-                     "innermost block that needs to be closed is 'if'.")
-        assert_error('{% if foo %}',
-                     "Unexpected end of template. Jinja was looking for the "
-                     "following tags: 'elif' or 'else' or 'endif'. The "
-                     "innermost block that needs to be closed is 'if'.")
-        assert_error('{% for item in seq %}',
-                     "Unexpected end of template. Jinja was looking for the "
-                     "following tags: 'endfor' or 'else'. The innermost block "
-                     "that needs to be closed is 'for'.")
-        assert_error('{% block foo-bar-baz %}',
-                     "Block names in Jinja have to be valid Python identifiers "
-                     "and may not contain hypens, use an underscore instead.")
-        assert_error('{% unknown_tag %}',
-                     "Encountered unknown tag 'unknown_tag'.")
-
-
-class SyntaxTestCase(JinjaTestCase):
-
-    def test_call(self):
-        env = Environment()
-        env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
-        tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
-        assert tmpl.render() == 'abdfh'
-
-    def test_slicing(self):
-        tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
-        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
-
-    def test_attr(self):
-        tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
-        assert tmpl.render(foo={'bar': 42}) == '42|42'
-
-    def test_subscript(self):
-        tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
-        assert tmpl.render(foo=[0, 1, 2]) == '0|2'
-
-    def test_tuple(self):
-        tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
-        assert tmpl.render() == '()|(1,)|(1, 2)'
-
-    def test_math(self):
-        tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
-        assert tmpl.render() == '1.5|8'
-
-    def test_div(self):
-        tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
-        assert tmpl.render() == '1|1.5|1'
-
-    def test_unary(self):
-        tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
-        assert tmpl.render() == '3|-3'
-
-    def test_concat(self):
-        tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
-        assert tmpl.render() == '[1, 2]foo'
-
-    def test_compare(self):
-        tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
-                               '{{ 2 == 2 }}|{{ 1 <= 1 }}')
-        assert tmpl.render() == 'True|True|True|True|True'
-
-    def test_inop(self):
-        tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
-        assert tmpl.render() == 'True|False'
-
-    def test_literals(self):
-        tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
-        assert tmpl.render().lower() == '[]|{}|()'
-
-    def test_bool(self):
-        tmpl = env.from_string('{{ true and false }}|{{ false '
-                               'or true }}|{{ not false }}')
-        assert tmpl.render() == 'False|True|True'
-
-    def test_grouping(self):
-        tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
-        assert tmpl.render() == 'False'
-
-    def test_django_attr(self):
-        tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
-        assert tmpl.render() == '1|1'
-
-    def test_conditional_expression(self):
-        tmpl = env.from_string('''{{ 0 if true else 1 }}''')
-        assert tmpl.render() == '0'
-
-    def test_short_conditional_expression(self):
-        tmpl = env.from_string('<{{ 1 if false }}>')
-        assert tmpl.render() == '<>'
-
-        tmpl = env.from_string('<{{ (1 if false).bar }}>')
-        self.assert_raises(UndefinedError, tmpl.render)
-
-    def test_filter_priority(self):
-        tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
-        assert tmpl.render() == 'FOOBAR'
-
-    def test_function_calls(self):
-        tests = [
-            (True, '*foo, bar'),
-            (True, '*foo, *bar'),
-            (True, '*foo, bar=42'),
-            (True, '**foo, *bar'),
-            (True, '**foo, bar'),
-            (False, 'foo, bar'),
-            (False, 'foo, bar=42'),
-            (False, 'foo, bar=23, *args'),
-            (False, 'a, b=c, *d, **e'),
-            (False, '*foo, **bar')
-        ]
-        for should_fail, sig in tests:
-            if should_fail:
-                self.assert_raises(TemplateSyntaxError,
-                    env.from_string, '{{ foo(%s) }}' % sig)
-            else:
-                env.from_string('foo(%s)' % sig)
-
-    def test_tuple_expr(self):
-        for tmpl in [
-            '{{ () }}',
-            '{{ (1, 2) }}',
-            '{{ (1, 2,) }}',
-            '{{ 1, }}',
-            '{{ 1, 2 }}',
-            '{% for foo, bar in seq %}...{% endfor %}',
-            '{% for x in foo, bar %}...{% endfor %}',
-            '{% for x in foo, %}...{% endfor %}'
-        ]:
-            assert env.from_string(tmpl)
-
-    def test_trailing_comma(self):
-        tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
-        assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
-
-    def test_block_end_name(self):
-        env.from_string('{% block foo %}...{% endblock foo %}')
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{% block x %}{% endblock y %}')
-
-    def test_contant_casing(self):
-        for const in True, False, None:
-            tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
-                str(const), str(const).lower(), str(const).upper()
-            ))
-            assert tmpl.render() == '%s|%s|' % (const, const)
-
-    def test_test_chaining(self):
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{{ foo is string is sequence }}')
-        env.from_string('{{ 42 is string or 42 is number }}'
-            ).render() == 'True'
-
-    def test_string_concatenation(self):
-        tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
-        assert tmpl.render() == 'foobarbaz'
-
-    def test_notin(self):
-        bar = xrange(100)
-        tmpl = env.from_string('''{{ not 42 in bar }}''')
-        assert tmpl.render(bar=bar) == unicode(not 42 in bar)
-
-    def test_implicit_subscribed_tuple(self):
-        class Foo(object):
-            def __getitem__(self, x):
-                return x
-        t = env.from_string('{{ foo[1, 2] }}')
-        assert t.render(foo=Foo()) == u'(1, 2)'
-
-    def test_raw2(self):
-        tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
-        assert tmpl.render() == '{{ FOO }} and {% BAR %}'
-
-    def test_const(self):
-        tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
-                               '{{ none is defined }}|{{ missing is defined }}')
-        assert tmpl.render() == 'True|False|None|True|False'
-
-    def test_neg_filter_priority(self):
-        node = env.parse('{{ -1|foo }}')
-        assert isinstance(node.body[0].nodes[0], nodes.Filter)
-        assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
-
-    def test_const_assign(self):
-        constass1 = '''{% set true = 42 %}'''
-        constass2 = '''{% for none in seq %}{% endfor %}'''
-        for tmpl in constass1, constass2:
-            self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
-
-    def test_localset(self):
-        tmpl = env.from_string('''{% set foo = 0 %}\
-{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
-{{ foo }}''')
-        assert tmpl.render() == '0'
-
-    def test_parse_unary(self):
-        tmpl = env.from_string('{{ -foo["bar"] }}')
-        assert tmpl.render(foo={'bar': 42}) == '-42'
-        tmpl = env.from_string('{{ -foo["bar"]|abs }}')
-        assert tmpl.render(foo={'bar': 42}) == '42'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LexerTestCase))
-    suite.addTest(unittest.makeSuite(ParserTestCase))
-    suite.addTest(unittest.makeSuite(SyntaxTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py
deleted file mode 100644
index 0ff0d04..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/loader.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.loader
-    ~~~~~~~~~~~~~~~~~~~~~~~
-
-    Test the loaders.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import time
-import tempfile
-import shutil
-import unittest
-
-from jinja2.testsuite import JinjaTestCase, dict_loader, \
-     package_loader, filesystem_loader, function_loader, \
-     choice_loader, prefix_loader
-
-from jinja2 import Environment, loaders
-from jinja2.loaders import split_template_path
-from jinja2.exceptions import TemplateNotFound
-
-
-class LoaderTestCase(JinjaTestCase):
-
-    def test_dict_loader(self):
-        env = Environment(loader=dict_loader)
-        tmpl = env.get_template('justdict.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_package_loader(self):
-        env = Environment(loader=package_loader)
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_filesystem_loader(self):
-        env = Environment(loader=filesystem_loader)
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        tmpl = env.get_template('foo/test.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_choice_loader(self):
-        env = Environment(loader=choice_loader)
-        tmpl = env.get_template('justdict.html')
-        assert tmpl.render().strip() == 'FOO'
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_function_loader(self):
-        env = Environment(loader=function_loader)
-        tmpl = env.get_template('justfunction.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-    def test_prefix_loader(self):
-        env = Environment(loader=prefix_loader)
-        tmpl = env.get_template('a/test.html')
-        assert tmpl.render().strip() == 'BAR'
-        tmpl = env.get_template('b/justdict.html')
-        assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing')
-
-    def test_caching(self):
-        changed = False
-        class TestLoader(loaders.BaseLoader):
-            def get_source(self, environment, template):
-                return u'foo', None, lambda: not changed
-        env = Environment(loader=TestLoader(), cache_size=-1)
-        tmpl = env.get_template('template')
-        assert tmpl is env.get_template('template')
-        changed = True
-        assert tmpl is not env.get_template('template')
-        changed = False
-
-        env = Environment(loader=TestLoader(), cache_size=0)
-        assert env.get_template('template') \
-               is not env.get_template('template')
-
-        env = Environment(loader=TestLoader(), cache_size=2)
-        t1 = env.get_template('one')
-        t2 = env.get_template('two')
-        assert t2 is env.get_template('two')
-        assert t1 is env.get_template('one')
-        t3 = env.get_template('three')
-        assert 'one' in env.cache
-        assert 'two' not in env.cache
-        assert 'three' in env.cache
-
-    def test_split_template_path(self):
-        assert split_template_path('foo/bar') == ['foo', 'bar']
-        assert split_template_path('./foo/bar') == ['foo', 'bar']
-        self.assert_raises(TemplateNotFound, split_template_path, '../foo')
-
-
-class ModuleLoaderTestCase(JinjaTestCase):
-    archive = None
-
-    def compile_down(self, zip='deflated', py_compile=False):
-        super(ModuleLoaderTestCase, self).setup()
-        log = []
-        self.reg_env = Environment(loader=prefix_loader)
-        if zip is not None:
-            self.archive = tempfile.mkstemp(suffix='.zip')[1]
-        else:
-            self.archive = tempfile.mkdtemp()
-        self.reg_env.compile_templates(self.archive, zip=zip,
-                                       log_function=log.append,
-                                       py_compile=py_compile)
-        self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
-        return ''.join(log)
-
-    def teardown(self):
-        super(ModuleLoaderTestCase, self).teardown()
-        if hasattr(self, 'mod_env'):
-            if os.path.isfile(self.archive):
-                os.remove(self.archive)
-            else:
-                shutil.rmtree(self.archive)
-            self.archive = None
-
-    def test_log(self):
-        log = self.compile_down()
-        assert 'Compiled "a/foo/test.html" as ' \
-               'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
-        assert 'Finished compiling templates' in log
-        assert 'Could not compile "a/syntaxerror.html": ' \
-               'Encountered unknown tag \'endif\'' in log
-
-    def _test_common(self):
-        tmpl1 = self.reg_env.get_template('a/test.html')
-        tmpl2 = self.mod_env.get_template('a/test.html')
-        assert tmpl1.render() == tmpl2.render()
-
-        tmpl1 = self.reg_env.get_template('b/justdict.html')
-        tmpl2 = self.mod_env.get_template('b/justdict.html')
-        assert tmpl1.render() == tmpl2.render()
-
-    def test_deflated_zip_compile(self):
-        self.compile_down(zip='deflated')
-        self._test_common()
-
-    def test_stored_zip_compile(self):
-        self.compile_down(zip='stored')
-        self._test_common()
-
-    def test_filesystem_compile(self):
-        self.compile_down(zip=None)
-        self._test_common()
-
-    def test_weak_references(self):
-        self.compile_down()
-        tmpl = self.mod_env.get_template('a/test.html')
-        key = loaders.ModuleLoader.get_template_key('a/test.html')
-        name = self.mod_env.loader.module.__name__
-
-        assert hasattr(self.mod_env.loader.module, key)
-        assert name in sys.modules
-
-        # unset all, ensure the module is gone from sys.modules
-        self.mod_env = tmpl = None
-
-        try:
-            import gc
-            gc.collect()
-        except:
-            pass
-
-        assert name not in sys.modules
-
-    def test_byte_compilation(self):
-        log = self.compile_down(py_compile=True)
-        assert 'Byte-compiled "a/test.html"' in log
-        tmpl1 = self.mod_env.get_template('a/test.html')
-        mod = self.mod_env.loader.module. \
-            tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
-        assert mod.__file__.endswith('.pyc')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LoaderTestCase))
-    suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py
deleted file mode 100644
index a39c3cb..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/regression.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.regression
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests corner cases and bugs.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
-     TemplateNotFound, PrefixLoader
-
-env = Environment()
-
-
-class CornerTestCase(JinjaTestCase):
-
-    def test_assigned_scoping(self):
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) -%}
-            [{{ item }}]
-        {%- endfor %}
-        {{- item -}}
-        ''')
-        assert t.render(item=42) == '[1][2][3][4]42'
-
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) -%}
-            [{{ item }}]
-        {%- endfor %}
-        {%- set item = 42 %}
-        {{- item -}}
-        ''')
-        assert t.render() == '[1][2][3][4]42'
-
-        t = env.from_string('''
-        {%- set item = 42 %}
-        {%- for item in (1, 2, 3, 4) -%}
-            [{{ item }}]
-        {%- endfor %}
-        {{- item -}}
-        ''')
-        assert t.render() == '[1][2][3][4]42'
-
-    def test_closure_scoping(self):
-        t = env.from_string('''
-        {%- set wrapper = "<FOO>" %}
-        {%- for item in (1, 2, 3, 4) %}
-            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
-            {{- wrapper() }}
-        {%- endfor %}
-        {{- wrapper -}}
-        ''')
-        assert t.render() == '[1][2][3][4]<FOO>'
-
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) %}
-            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
-            {{- wrapper() }}
-        {%- endfor %}
-        {%- set wrapper = "<FOO>" %}
-        {{- wrapper -}}
-        ''')
-        assert t.render() == '[1][2][3][4]<FOO>'
-
-        t = env.from_string('''
-        {%- for item in (1, 2, 3, 4) %}
-            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
-            {{- wrapper() }}
-        {%- endfor %}
-        {{- wrapper -}}
-        ''')
-        assert t.render(wrapper=23) == '[1][2][3][4]23'
-
-
-class BugTestCase(JinjaTestCase):
-
-    def test_keyword_folding(self):
-        env = Environment()
-        env.filters['testing'] = lambda value, some: value + some
-        assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
-               .render() == 'teststuff'
-
-    def test_extends_output_bugs(self):
-        env = Environment(loader=DictLoader({
-            'parent.html': '(({% block title %}{% endblock %}))'
-        }))
-
-        t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
-                            '[[{% block title %}title{% endblock %}]]'
-                            '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
-        assert t.render(expr=False) == '[[title]](1)(2)(3)'
-        assert t.render(expr=True) == '((title))'
-
-    def test_urlize_filter_escaping(self):
-        tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
-        assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">http://www.example.org/&lt;foo</a>'
-
-    def test_loop_call_loop(self):
-        tmpl = env.from_string('''
-
-        {% macro test() %}
-            {{ caller() }}
-        {% endmacro %}
-
-        {% for num1 in range(5) %}
-            {% call test() %}
-                {% for num2 in range(10) %}
-                    {{ loop.index }}
-                {% endfor %}
-            {% endcall %}
-        {% endfor %}
-
-        ''')
-
-        assert tmpl.render().split() == map(unicode, range(1, 11)) * 5
-
-    def test_weird_inline_comment(self):
-        env = Environment(line_statement_prefix='%')
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '% for item in seq {# missing #}\n...% endfor')
-
-    def test_old_macro_loop_scoping_bug(self):
-        tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
-                               '{% macro i() %}3{% endmacro %}{{ i() }}')
-        assert tmpl.render() == '123'
-
-    def test_partial_conditional_assignments(self):
-        tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
-        assert tmpl.render(a=23) == '23'
-        assert tmpl.render(b=True) == '42'
-
-    def test_stacked_locals_scoping_bug(self):
-        env = Environment(line_statement_prefix='#')
-        t = env.from_string('''\
-# for j in [1, 2]:
-#   set x = 1
-#   for i in [1, 2]:
-#     print x
-#     if i % 2 == 0:
-#       set x = x + 1
-#     endif
-#   endfor
-# endfor
-# if a
-#   print 'A'
-# elif b
-#   print 'B'
-# elif c == d
-#   print 'C'
-# else
-#   print 'D'
-# endif
-    ''')
-        assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
-
-    def test_stacked_locals_scoping_bug_twoframe(self):
-        t = Template('''
-            {% set x = 1 %}
-            {% for item in foo %}
-                {% if item == 1 %}
-                    {% set x = 2 %}
-                {% endif %}
-            {% endfor %}
-            {{ x }}
-        ''')
-        rv = t.render(foo=[1]).strip()
-        assert rv == u'1'
-
-    def test_call_with_args(self):
-        t = Template("""{% macro dump_users(users) -%}
-        <ul>
-          {%- for user in users -%}
-            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
-          {%- endfor -%}
-          </ul>
-        {%- endmacro -%}
-
-        {% call(user) dump_users(list_of_user) -%}
-          <dl>
-            <dl>Realname</dl>
-            <dd>{{ user.realname|e }}</dd>
-            <dl>Description</dl>
-            <dd>{{ user.description }}</dd>
-          </dl>
-        {% endcall %}""")
-
-        assert [x.strip() for x in t.render(list_of_user=[{
-            'username':'apo',
-            'realname':'something else',
-            'description':'test'
-        }]).splitlines()] == [
-            u'<ul><li><p>apo</p><dl>',
-            u'<dl>Realname</dl>',
-            u'<dd>something else</dd>',
-            u'<dl>Description</dl>',
-            u'<dd>test</dd>',
-            u'</dl>',
-            u'</li></ul>'
-        ]
-
-    def test_empty_if_condition_fails(self):
-        self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
-        self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
-        self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
-
-    def test_recursive_loop_bug(self):
-        tpl1 = Template("""
-        {% for p in foo recursive%}
-            {{p.bar}}
-            {% for f in p.fields recursive%}
-                {{f.baz}}
-                {{p.bar}}
-                {% if f.rec %}
-                    {{ loop(f.sub) }}
-                {% endif %}
-            {% endfor %}
-        {% endfor %}
-        """)
-
-        tpl2 = Template("""
-        {% for p in foo%}
-            {{p.bar}}
-            {% for f in p.fields recursive%}
-                {{f.baz}}
-                {{p.bar}}
-                {% if f.rec %}
-                    {{ loop(f.sub) }}
-                {% endif %}
-            {% endfor %}
-        {% endfor %}
-        """)
-
-    def test_correct_prefix_loader_name(self):
-        env = Environment(loader=PrefixLoader({
-            'foo':  DictLoader({})
-        }))
-        try:
-            env.get_template('foo/bar.html')
-        except TemplateNotFound, e:
-            assert e.name == 'foo/bar.html'
-        else:
-            assert False, 'expected error here'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(CornerTestCase))
-    suite.addTest(unittest.makeSuite(BugTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/__init__.py
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html
deleted file mode 100644
index 77669fa..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/broken.html
+++ /dev/null
@@ -1,3 +0,0 @@
-Before
-{{ fail() }}
-After

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html
deleted file mode 100644
index b7d6715..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/foo/test.html
+++ /dev/null
@@ -1 +0,0 @@
-FOO

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html
deleted file mode 100644
index f21b817..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/syntaxerror.html
+++ /dev/null
@@ -1,4 +0,0 @@
-Foo
-{% for item in broken %}
-  ...
-{% endif %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html b/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html
deleted file mode 100644
index ba578e4..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/res/templates/test.html
+++ /dev/null
@@ -1 +0,0 @@
-BAR

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py
deleted file mode 100644
index b2b4cf1..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/security.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.security
-    ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Checks the sandbox and other security features.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment
-from jinja2.sandbox import SandboxedEnvironment, \
-     ImmutableSandboxedEnvironment, unsafe
-from jinja2 import Markup, escape
-from jinja2.exceptions import SecurityError, TemplateSyntaxError
-
-
-class PrivateStuff(object):
-
-    def bar(self):
-        return 23
-
-    @unsafe
-    def foo(self):
-        return 42
-
-    def __repr__(self):
-        return 'PrivateStuff'
-
-
-class PublicStuff(object):
-    bar = lambda self: 23
-    _foo = lambda self: 42
-
-    def __repr__(self):
-        return 'PublicStuff'
-
-
-class SandboxTestCase(JinjaTestCase):
-
-    def test_unsafe(self):
-        env = SandboxedEnvironment()
-        self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
-                           foo=PrivateStuff())
-        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
-
-        self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
-                           foo=PublicStuff())
-        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
-        self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
-        self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
-        self.assert_raises(SecurityError, env.from_string(
-            "{{ foo.__class__.__subclasses__() }}").render, foo=42)
-
-    def test_immutable_environment(self):
-        env = ImmutableSandboxedEnvironment()
-        self.assert_raises(SecurityError, env.from_string(
-            '{{ [].append(23) }}').render)
-        self.assert_raises(SecurityError, env.from_string(
-            '{{ {1:2}.clear() }}').render)
-
-    def test_restricted(self):
-        env = SandboxedEnvironment()
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                      "{% for item.attribute in seq %}...{% endfor %}")
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                      "{% for foo, bar.baz in seq %}...{% endfor %}")
-
-    def test_markup_operations(self):
-        # adding two strings should escape the unsafe one
-        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
-        safe = Markup('<em>username</em>')
-        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
-
-        # string interpolations are safe to use too
-        assert Markup('<em>%s</em>') % '<bad user>' == \
-               '<em>&lt;bad user&gt;</em>'
-        assert Markup('<em>%(username)s</em>') % {
-            'username': '<bad user>'
-        } == '<em>&lt;bad user&gt;</em>'
-
-        # an escaped object is markup too
-        assert type(Markup('foo') + 'bar') is Markup
-
-        # and it implements __html__ by returning itself
-        x = Markup("foo")
-        assert x.__html__() is x
-
-        # it also knows how to treat __html__ objects
-        class Foo(object):
-            def __html__(self):
-                return '<em>awesome</em>'
-            def __unicode__(self):
-                return 'awesome'
-        assert Markup(Foo()) == '<em>awesome</em>'
-        assert Markup('<strong>%s</strong>') % Foo() == \
-               '<strong><em>awesome</em></strong>'
-
-        # escaping and unescaping
-        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
-        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
-        assert Markup("&lt;test&gt;").unescape() == "<test>"
-
-
-    def test_template_data(self):
-        env = Environment(autoescape=True)
-        t = env.from_string('{% macro say_hello(name) %}'
-                            '<p>Hello {{ name }}!</p>{% endmacro %}'
-                            '{{ say_hello("<blink>foo</blink>") }}')
-        escaped_out = '<p>Hello &lt;blink&gt;foo&lt;/blink&gt;!</p>'
-        assert t.render() == escaped_out
-        assert unicode(t.module) == escaped_out
-        assert escape(t.module) == escaped_out
-        assert t.module.say_hello('<blink>foo</blink>') == escaped_out
-        assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
-
-
-    def test_attr_filter(self):
-        env = SandboxedEnvironment()
-        tmpl = env.from_string('{{ 42|attr("__class__")|attr("__subclasses__")() }}')
-        self.assert_raises(SecurityError, tmpl.render)
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(SandboxTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py
deleted file mode 100644
index cd5006f..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/tests.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.tests
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Who tests the tests?
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Markup, Environment
-
-env = Environment()
-
-
-class TestsTestCase(JinjaTestCase):
-
-    def test_defined(self):
-        tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
-        assert tmpl.render() == 'False|True'
-
-    def test_even(self):
-        tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
-        assert tmpl.render() == 'False|True'
-
-    def test_odd(self):
-        tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
-        assert tmpl.render() == 'True|False'
-
-    def test_lower(self):
-        tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
-        assert tmpl.render() == 'True|False'
-
-    def test_typechecks(self):
-        tmpl = env.from_string('''
-            {{ 42 is undefined }}
-            {{ 42 is defined }}
-            {{ 42 is none }}
-            {{ none is none }}
-            {{ 42 is number }}
-            {{ 42 is string }}
-            {{ "foo" is string }}
-            {{ "foo" is sequence }}
-            {{ [1] is sequence }}
-            {{ range is callable }}
-            {{ 42 is callable }}
-            {{ range(5) is iterable }}
-        ''')
-        assert tmpl.render().split() == [
-            'False', 'True', 'False', 'True', 'True', 'False',
-            'True', 'True', 'True', 'True', 'False', 'True'
-        ]
-
-    def test_sequence(self):
-        tmpl = env.from_string(
-            '{{ [1, 2, 3] is sequence }}|'
-            '{{ "foo" is sequence }}|'
-            '{{ 42 is sequence }}'
-        )
-        assert tmpl.render() == 'True|True|False'
-
-    def test_upper(self):
-        tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
-        assert tmpl.render() == 'True|False'
-
-    def test_sameas(self):
-        tmpl = env.from_string('{{ foo is sameas false }}|'
-                               '{{ 0 is sameas false }}')
-        assert tmpl.render(foo=False) == 'True|False'
-
-    def test_no_paren_for_arg1(self):
-        tmpl = env.from_string('{{ foo is sameas none }}')
-        assert tmpl.render(foo=None) == 'True'
-
-    def test_escaped(self):
-        env = Environment(autoescape=True)
-        tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
-        assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(TestsTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py
deleted file mode 100644
index a402bbc..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/utils.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.utils
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests utilities jinja uses.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import gc
-import unittest
-
-import pickle
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment, Undefined, DebugUndefined, \
-     StrictUndefined, UndefinedError, Template, meta
-from jinja2.utils import LRUCache, escape, object_type_repr
-
-
-class LRUCacheTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        d = LRUCache(3)
-        d["a"] = 1
-        d["b"] = 2
-        d["c"] = 3
-        d["a"]
-        d["d"] = 4
-        assert len(d) == 3
-        assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d
-
-    def test_pickleable(self):
-        cache = LRUCache(2)
-        cache["foo"] = 42
-        cache["bar"] = 23
-        cache["foo"]
-
-        for protocol in range(3):
-            copy = pickle.loads(pickle.dumps(cache, protocol))
-            assert copy.capacity == cache.capacity
-            assert copy._mapping == cache._mapping
-            assert copy._queue == cache._queue
-
-
-class HelpersTestCase(JinjaTestCase):
-
-    def test_object_type_repr(self):
-        class X(object):
-            pass
-        self.assert_equal(object_type_repr(42), 'int object')
-        self.assert_equal(object_type_repr([]), 'list object')
-        self.assert_equal(object_type_repr(X()),
-                         'jinja2.testsuite.utils.X object')
-        self.assert_equal(object_type_repr(None), 'None')
-        self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
-
-
-class MarkupLeakTestCase(JinjaTestCase):
-
-    def test_markup_leaks(self):
-        counts = set()
-        for count in xrange(20):
-            for item in xrange(1000):
-                escape("foo")
-                escape("<foo>")
-                escape(u"foo")
-                escape(u"<foo>")
-            counts.add(len(gc.get_objects()))
-        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LRUCacheTestCase))
-    suite.addTest(unittest.makeSuite(HelpersTestCase))
-
-    # this test only tests the c extension
-    if not hasattr(escape, 'func_code'):
-        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
-
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/utils.py b/ambari-common/src/main/python/jinja2/jinja2/utils.py
deleted file mode 100644
index 7b77b8e..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/utils.py
+++ /dev/null
@@ -1,601 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.utils
-    ~~~~~~~~~~~~
-
-    Utility functions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import sys
-import errno
-try:
-    from thread import allocate_lock
-except ImportError:
-    from dummy_thread import allocate_lock
-from collections import deque
-from itertools import imap
-
-
-_word_split_re = re.compile(r'(\s+)')
-_punctuation_re = re.compile(
-    '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
-        '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
-        '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
-    )
-)
-_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
-_entity_re = re.compile(r'&([^;]+);')
-_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
-_digits = '0123456789'
-
-# special singleton representing missing values for the runtime
-missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
-
-# internal code
-internal_code = set()
-
-
-# concatenate a list of strings and convert them to unicode.
-# unfortunately there is a bug in python 2.4 and lower that causes
-# unicode.join trash the traceback.
-_concat = u''.join
-try:
-    def _test_gen_bug():
-        raise TypeError(_test_gen_bug)
-        yield None
-    _concat(_test_gen_bug())
-except TypeError, _error:
-    if not _error.args or _error.args[0] is not _test_gen_bug:
-        def concat(gen):
-            try:
-                return _concat(list(gen))
-            except:
-                # this hack is needed so that the current frame
-                # does not show up in the traceback.
-                exc_type, exc_value, tb = sys.exc_info()
-                raise exc_type, exc_value, tb.tb_next
-    else:
-        concat = _concat
-    del _test_gen_bug, _error
-
-
-# for python 2.x we create outselves a next() function that does the
-# basics without exception catching.
-try:
-    next = next
-except NameError:
-    def next(x):
-        return x.next()
-
-
-# if this python version is unable to deal with unicode filenames
-# when passed to encode we let this function encode it properly.
-# This is used in a couple of places.  As far as Jinja is concerned
-# filenames are unicode *or* bytestrings in 2.x and unicode only in
-# 3.x because compile cannot handle bytes
-if sys.version_info < (3, 0):
-    def _encode_filename(filename):
-        if isinstance(filename, unicode):
-            return filename.encode('utf-8')
-        return filename
-else:
-    def _encode_filename(filename):
-        assert filename is None or isinstance(filename, str), \
-            'filenames must be strings'
-        return filename
-
-from keyword import iskeyword as is_python_keyword
-
-
-# common types.  These do exist in the special types module too which however
-# does not exist in IronPython out of the box.  Also that way we don't have
-# to deal with implementation specific stuff here
-class _C(object):
-    def method(self): pass
-def _func():
-    yield None
-FunctionType = type(_func)
-GeneratorType = type(_func())
-MethodType = type(_C.method)
-CodeType = type(_C.method.func_code)
-try:
-    raise TypeError()
-except TypeError:
-    _tb = sys.exc_info()[2]
-    TracebackType = type(_tb)
-    FrameType = type(_tb.tb_frame)
-del _C, _tb, _func
-
-
-def contextfunction(f):
-    """This decorator can be used to mark a function or method context callable.
-    A context callable is passed the active :class:`Context` as first argument when
-    called from the template.  This is useful if a function wants to get access
-    to the context or functions provided on the context object.  For example
-    a function that returns a sorted list of template variables the current
-    template exports could look like this::
-
-        @contextfunction
-        def get_exported_names(context):
-            return sorted(context.exported_vars)
-    """
-    f.contextfunction = True
-    return f
-
-
-def evalcontextfunction(f):
-    """This decoraotr can be used to mark a function or method as an eval
-    context callable.  This is similar to the :func:`contextfunction`
-    but instead of passing the context, an evaluation context object is
-    passed.  For more information about the eval context, see
-    :ref:`eval-context`.
-
-    .. versionadded:: 2.4
-    """
-    f.evalcontextfunction = True
-    return f
-
-
-def environmentfunction(f):
-    """This decorator can be used to mark a function or method as environment
-    callable.  This decorator works exactly like the :func:`contextfunction`
-    decorator just that the first argument is the active :class:`Environment`
-    and not context.
-    """
-    f.environmentfunction = True
-    return f
-
-
-def internalcode(f):
-    """Marks the function as internally used"""
-    internal_code.add(f.func_code)
-    return f
-
-
-def is_undefined(obj):
-    """Check if the object passed is undefined.  This does nothing more than
-    performing an instance check against :class:`Undefined` but looks nicer.
-    This can be used for custom filters or tests that want to react to
-    undefined variables.  For example a custom default filter can look like
-    this::
-
-        def default(var, default=''):
-            if is_undefined(var):
-                return default
-            return var
-    """
-    from jinja2.runtime import Undefined
-    return isinstance(obj, Undefined)
-
-
-def consume(iterable):
-    """Consumes an iterable without doing anything with it."""
-    for event in iterable:
-        pass
-
-
-def clear_caches():
-    """Jinja2 keeps internal caches for environments and lexers.  These are
-    used so that Jinja2 doesn't have to recreate environments and lexers all
-    the time.  Normally you don't have to care about that but if you are
-    messuring memory consumption you may want to clean the caches.
-    """
-    from jinja2.environment import _spontaneous_environments
-    from jinja2.lexer import _lexer_cache
-    _spontaneous_environments.clear()
-    _lexer_cache.clear()
-
-
-def import_string(import_name, silent=False):
-    """Imports an object based on a string.  This use useful if you want to
-    use import paths as endpoints or something similar.  An import path can
-    be specified either in dotted notation (``xml.sax.saxutils.escape``)
-    or with a colon as object delimiter (``xml.sax.saxutils:escape``).
-
-    If the `silent` is True the return value will be `None` if the import
-    fails.
-
-    :return: imported object
-    """
-    try:
-        if ':' in import_name:
-            module, obj = import_name.split(':', 1)
-        elif '.' in import_name:
-            items = import_name.split('.')
-            module = '.'.join(items[:-1])
-            obj = items[-1]
-        else:
-            return __import__(import_name)
-        return getattr(__import__(module, None, None, [obj]), obj)
-    except (ImportError, AttributeError):
-        if not silent:
-            raise
-
-
-def open_if_exists(filename, mode='rb'):
-    """Returns a file descriptor for the filename if that file exists,
-    otherwise `None`.
-    """
-    try:
-        return open(filename, mode)
-    except IOError, e:
-        if e.errno not in (errno.ENOENT, errno.EISDIR):
-            raise
-
-
-def object_type_repr(obj):
-    """Returns the name of the object's type.  For some recognized
-    singletons the name of the object is returned instead. (For
-    example for `None` and `Ellipsis`).
-    """
-    if obj is None:
-        return 'None'
-    elif obj is Ellipsis:
-        return 'Ellipsis'
-    # __builtin__ in 2.x, builtins in 3.x
-    if obj.__class__.__module__ in ('__builtin__', 'builtins'):
-        name = obj.__class__.__name__
-    else:
-        name = obj.__class__.__module__ + '.' + obj.__class__.__name__
-    return '%s object' % name
-
-
-def pformat(obj, verbose=False):
-    """Prettyprint an object.  Either use the `pretty` library or the
-    builtin `pprint`.
-    """
-    try:
-        from pretty import pretty
-        return pretty(obj, verbose=verbose)
-    except ImportError:
-        from pprint import pformat
-        return pformat(obj)
-
-
-def urlize(text, trim_url_limit=None, nofollow=False):
-    """Converts any URLs in text into clickable links. Works on http://,
-    https:// and www. links. Links can have trailing punctuation (periods,
-    commas, close-parens) and leading punctuation (opening parens) and
-    it'll still do the right thing.
-
-    If trim_url_limit is not None, the URLs in link text will be limited
-    to trim_url_limit characters.
-
-    If nofollow is True, the URLs in link text will get a rel="nofollow"
-    attribute.
-    """
-    trim_url = lambda x, limit=trim_url_limit: limit is not None \
-                         and (x[:limit] + (len(x) >=limit and '...'
-                         or '')) or x
-    words = _word_split_re.split(unicode(escape(text)))
-    nofollow_attr = nofollow and ' rel="nofollow"' or ''
-    for i, word in enumerate(words):
-        match = _punctuation_re.match(word)
-        if match:
-            lead, middle, trail = match.groups()
-            if middle.startswith('www.') or (
-                '@' not in middle and
-                not middle.startswith('http://') and
-                len(middle) > 0 and
-                middle[0] in _letters + _digits and (
-                    middle.endswith('.org') or
-                    middle.endswith('.net') or
-                    middle.endswith('.com')
-                )):
-                middle = '<a href="http://%s"%s>%s</a>' % (middle,
-                    nofollow_attr, trim_url(middle))
-            if middle.startswith('http://') or \
-               middle.startswith('https://'):
-                middle = '<a href="%s"%s>%s</a>' % (middle,
-                    nofollow_attr, trim_url(middle))
-            if '@' in middle and not middle.startswith('www.') and \
-               not ':' in middle and _simple_email_re.match(middle):
-                middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
-            if lead + middle + trail != word:
-                words[i] = lead + middle + trail
-    return u''.join(words)
-
-
-def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
-    """Generate some lorem impsum for the template."""
-    from jinja2.constants import LOREM_IPSUM_WORDS
-    from random import choice, randrange
-    words = LOREM_IPSUM_WORDS.split()
-    result = []
-
-    for _ in xrange(n):
-        next_capitalized = True
-        last_comma = last_fullstop = 0
-        word = None
-        last = None
-        p = []
-
-        # each paragraph contains out of 20 to 100 words.
-        for idx, _ in enumerate(xrange(randrange(min, max))):
-            while True:
-                word = choice(words)
-                if word != last:
-                    last = word
-                    break
-            if next_capitalized:
-                word = word.capitalize()
-                next_capitalized = False
-            # add commas
-            if idx - randrange(3, 8) > last_comma:
-                last_comma = idx
-                last_fullstop += 2
-                word += ','
-            # add end of sentences
-            if idx - randrange(10, 20) > last_fullstop:
-                last_comma = last_fullstop = idx
-                word += '.'
-                next_capitalized = True
-            p.append(word)
-
-        # ensure that the paragraph ends with a dot.
-        p = u' '.join(p)
-        if p.endswith(','):
-            p = p[:-1] + '.'
-        elif not p.endswith('.'):
-            p += '.'
-        result.append(p)
-
-    if not html:
-        return u'\n\n'.join(result)
-    return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
-
-
-class LRUCache(object):
-    """A simple LRU Cache implementation."""
-
-    # this is fast for small capacities (something below 1000) but doesn't
-    # scale.  But as long as it's only used as storage for templates this
-    # won't do any harm.
-
-    def __init__(self, capacity):
-        self.capacity = capacity
-        self._mapping = {}
-        self._queue = deque()
-        self._postinit()
-
-    def _postinit(self):
-        # alias all queue methods for faster lookup
-        self._popleft = self._queue.popleft
-        self._pop = self._queue.pop
-        if hasattr(self._queue, 'remove'):
-            self._remove = self._queue.remove
-        self._wlock = allocate_lock()
-        self._append = self._queue.append
-
-    def _remove(self, obj):
-        """Python 2.4 compatibility."""
-        for idx, item in enumerate(self._queue):
-            if item == obj:
-                del self._queue[idx]
-                break
-
-    def __getstate__(self):
-        return {
-            'capacity':     self.capacity,
-            '_mapping':     self._mapping,
-            '_queue':       self._queue
-        }
-
-    def __setstate__(self, d):
-        self.__dict__.update(d)
-        self._postinit()
-
-    def __getnewargs__(self):
-        return (self.capacity,)
-
-    def copy(self):
-        """Return an shallow copy of the instance."""
-        rv = self.__class__(self.capacity)
-        rv._mapping.update(self._mapping)
-        rv._queue = deque(self._queue)
-        return rv
-
-    def get(self, key, default=None):
-        """Return an item from the cache dict or `default`"""
-        try:
-            return self[key]
-        except KeyError:
-            return default
-
-    def setdefault(self, key, default=None):
-        """Set `default` if the key is not in the cache otherwise
-        leave unchanged. Return the value of this key.
-        """
-        try:
-            return self[key]
-        except KeyError:
-            self[key] = default
-            return default
-
-    def clear(self):
-        """Clear the cache."""
-        self._wlock.acquire()
-        try:
-            self._mapping.clear()
-            self._queue.clear()
-        finally:
-            self._wlock.release()
-
-    def __contains__(self, key):
-        """Check if a key exists in this cache."""
-        return key in self._mapping
-
-    def __len__(self):
-        """Return the current size of the cache."""
-        return len(self._mapping)
-
-    def __repr__(self):
-        return '<%s %r>' % (
-            self.__class__.__name__,
-            self._mapping
-        )
-
-    def __getitem__(self, key):
-        """Get an item from the cache. Moves the item up so that it has the
-        highest priority then.
-
-        Raise an `KeyError` if it does not exist.
-        """
-        rv = self._mapping[key]
-        if self._queue[-1] != key:
-            try:
-                self._remove(key)
-            except ValueError:
-                # if something removed the key from the container
-                # when we read, ignore the ValueError that we would
-                # get otherwise.
-                pass
-            self._append(key)
-        return rv
-
-    def __setitem__(self, key, value):
-        """Sets the value for an item. Moves the item up so that it
-        has the highest priority then.
-        """
-        self._wlock.acquire()
-        try:
-            if key in self._mapping:
-                try:
-                    self._remove(key)
-                except ValueError:
-                    # __getitem__ is not locked, it might happen
-                    pass
-            elif len(self._mapping) == self.capacity:
-                del self._mapping[self._popleft()]
-            self._append(key)
-            self._mapping[key] = value
-        finally:
-            self._wlock.release()
-
-    def __delitem__(self, key):
-        """Remove an item from the cache dict.
-        Raise an `KeyError` if it does not exist.
-        """
-        self._wlock.acquire()
-        try:
-            del self._mapping[key]
-            try:
-                self._remove(key)
-            except ValueError:
-                # __getitem__ is not locked, it might happen
-                pass
-        finally:
-            self._wlock.release()
-
-    def items(self):
-        """Return a list of items."""
-        result = [(key, self._mapping[key]) for key in list(self._queue)]
-        result.reverse()
-        return result
-
-    def iteritems(self):
-        """Iterate over all items."""
-        return iter(self.items())
-
-    def values(self):
-        """Return a list of all values."""
-        return [x[1] for x in self.items()]
-
-    def itervalue(self):
-        """Iterate over all values."""
-        return iter(self.values())
-
-    def keys(self):
-        """Return a list of all keys ordered by most recent usage."""
-        return list(self)
-
-    def iterkeys(self):
-        """Iterate over all keys in the cache dict, ordered by
-        the most recent usage.
-        """
-        return reversed(tuple(self._queue))
-
-    __iter__ = iterkeys
-
-    def __reversed__(self):
-        """Iterate over the values in the cache dict, oldest items
-        coming first.
-        """
-        return iter(tuple(self._queue))
-
-    __copy__ = copy
-
-
-# register the LRU cache as mutable mapping if possible
-try:
-    from collections import MutableMapping
-    MutableMapping.register(LRUCache)
-except ImportError:
-    pass
-
-
-class Cycler(object):
-    """A cycle helper for templates."""
-
-    def __init__(self, *items):
-        if not items:
-            raise RuntimeError('at least one item has to be provided')
-        self.items = items
-        self.reset()
-
-    def reset(self):
-        """Resets the cycle."""
-        self.pos = 0
-
-    @property
-    def current(self):
-        """Returns the current item."""
-        return self.items[self.pos]
-
-    def next(self):
-        """Goes one item ahead and returns it."""
-        rv = self.current
-        self.pos = (self.pos + 1) % len(self.items)
-        return rv
-
-
-class Joiner(object):
-    """A joining helper for templates."""
-
-    def __init__(self, sep=u', '):
-        self.sep = sep
-        self.used = False
-
-    def __call__(self):
-        if not self.used:
-            self.used = True
-            return u''
-        return self.sep
-
-
-# try markupsafe first, if that fails go with Jinja2's bundled version
-# of markupsafe.  Markupsafe was previously Jinja2's implementation of
-# the Markup object but was moved into a separate package in a patchleve
-# release
-try:
-    from markupsafe import Markup, escape, soft_unicode
-except ImportError:
-    from jinja2._markupsafe import Markup, escape, soft_unicode
-
-
-# partials
-try:
-    from functools import partial
-except ImportError:
-    class partial(object):
-        def __init__(self, _func, *args, **kwargs):
-            self._func = _func
-            self._args = args
-            self._kwargs = kwargs
-        def __call__(self, *args, **kwargs):
-            kwargs.update(self._kwargs)
-            return self._func(*(self._args + args), **kwargs)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/visitor.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/visitor.py b/ambari-common/src/main/python/jinja2/jinja2/visitor.py
deleted file mode 100644
index 413e7c3..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/visitor.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.visitor
-    ~~~~~~~~~~~~~~
-
-    This module implements a visitor for the nodes.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from jinja2.nodes import Node
-
-
-class NodeVisitor(object):
-    """Walks the abstract syntax tree and call visitor functions for every
-    node found.  The visitor functions may return values which will be
-    forwarded by the `visit` method.
-
-    Per default the visitor functions for the nodes are ``'visit_'`` +
-    class name of the node.  So a `TryFinally` node visit function would
-    be `visit_TryFinally`.  This behavior can be changed by overriding
-    the `get_visitor` function.  If no visitor function exists for a node
-    (return value `None`) the `generic_visit` visitor is used instead.
-    """
-
-    def get_visitor(self, node):
-        """Return the visitor function for this node or `None` if no visitor
-        exists for this node.  In that case the generic visit function is
-        used instead.
-        """
-        method = 'visit_' + node.__class__.__name__
-        return getattr(self, method, None)
-
-    def visit(self, node, *args, **kwargs):
-        """Visit a node."""
-        f = self.get_visitor(node)
-        if f is not None:
-            return f(node, *args, **kwargs)
-        return self.generic_visit(node, *args, **kwargs)
-
-    def generic_visit(self, node, *args, **kwargs):
-        """Called if no explicit visitor function exists for a node."""
-        for node in node.iter_child_nodes():
-            self.visit(node, *args, **kwargs)
-
-
-class NodeTransformer(NodeVisitor):
-    """Walks the abstract syntax tree and allows modifications of nodes.
-
-    The `NodeTransformer` will walk the AST and use the return value of the
-    visitor functions to replace or remove the old node.  If the return
-    value of the visitor function is `None` the node will be removed
-    from the previous location otherwise it's replaced with the return
-    value.  The return value may be the original node in which case no
-    replacement takes place.
-    """
-
-    def generic_visit(self, node, *args, **kwargs):
-        for field, old_value in node.iter_fields():
-            if isinstance(old_value, list):
-                new_values = []
-                for value in old_value:
-                    if isinstance(value, Node):
-                        value = self.visit(value, *args, **kwargs)
-                        if value is None:
-                            continue
-                        elif not isinstance(value, Node):
-                            new_values.extend(value)
-                            continue
-                    new_values.append(value)
-                old_value[:] = new_values
-            elif isinstance(old_value, Node):
-                new_node = self.visit(old_value, *args, **kwargs)
-                if new_node is None:
-                    delattr(node, field)
-                else:
-                    setattr(node, field, new_node)
-        return node
-
-    def visit_list(self, node, *args, **kwargs):
-        """As transformers may return lists in some places this method
-        can be used to enforce a list as return value.
-        """
-        rv = self.visit(node, *args, **kwargs)
-        if not isinstance(rv, list):
-            rv = [rv]
-        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/scripts/pylintrc
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/scripts/pylintrc b/ambari-common/src/main/python/jinja2/scripts/pylintrc
deleted file mode 100644
index 4f85b49..0000000
--- a/ambari-common/src/main/python/jinja2/scripts/pylintrc
+++ /dev/null
@@ -1,301 +0,0 @@
-# lint Python modules using external checkers.
-# 
-# This is the main checker controling the other ones and the reports
-# generation. It is itself both a raw checker and an astng checker in order
-# to:
-# * handle message activation / deactivation at the module level
-# * handle some basic but necessary stats'data (number of classes, methods...)
-# 
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Profiled execution.
-profile=no
-
-# Add <file or directory> to the black list. It should be a base name, not a
-# path. You may set this option multiple times.
-ignore=.svn
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# Set the cache size for astng objects.
-cache-size=500
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
-[MESSAGES CONTROL]
-
-# Enable only checker(s) with the given id(s). This option conflict with the
-# disable-checker option
-#enable-checker=
-
-# Enable all checker(s) except those with the given id(s). This option conflict
-# with the disable-checker option
-#disable-checker=
-
-# Enable all messages in the listed categories.
-#enable-msg-cat=
-
-# Disable all messages in the listed categories.
-#disable-msg-cat=
-
-# Enable the message(s) with the given id(s).
-#enable-msg=
-
-# Disable the message(s) with the given id(s).
-disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201
-
-
-[REPORTS]
-
-# set the output format. Available formats are text, parseable, colorized and
-# html
-output-format=colorized
-
-# Include message's id in output
-include-ids=yes
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells wether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note).You have access to the variables errors warning, statement which
-# respectivly contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (R0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (R0004).
-comment=no
-
-# Enable the report(s) with the given id(s).
-#enable-report=
-
-# Disable the report(s) with the given id(s).
-#disable-report=
-
-
-# checks for
-# * unused variables / imports
-# * undefined variables
-# * redefinition of variable from builtins or from an outer scope
-# * use of variable before assigment
-# 
-[VARIABLES]
-
-# Tells wether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching names used for dummy variables (i.e. not used).
-dummy-variables-rgx=_|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-
-# try to find bugs in the code using type inference
-# 
-[TYPECHECK]
-
-# Tells wether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# When zope mode is activated, consider the acquired-members option to ignore
-# access to some undefined attributes.
-zope=no
-
-# List of members which are usually get through zope's acquisition mecanism and
-# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
-acquired-members=REQUEST,acl_users,aq_parent
-
-
-# checks for :
-# * doc strings
-# * modules / classes / functions / methods / arguments / variables name
-# * number of arguments, local variables, branchs, returns and statements in
-# functions, methods
-# * required module attributes
-# * dangerous default values as arguments
-# * redefinition of function / method / class
-# * uses of the global statement
-# 
-[BASIC]
-
-# Required attributes for module, separated by a comma
-required-attributes=
-
-# Regular expression which should only match functions or classes name which do
-# not require a docstring
-no-docstring-rgx=__.*__
-
-# Regular expression which should only match correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression which should only match correct module level names
-const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
-
-# Regular expression which should only match correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression which should only match correct function names
-function-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct method names
-method-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct instance attribute names
-attr-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct argument names
-argument-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct variable names
-variable-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct list comprehension /
-# generator expression variable names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=apply,input
-
-
-# checks for sign of poor/misdesign:
-# * number of methods, attributes, local variables...
-# * size, complexity of functions, methods
-# 
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=12
-
-# Maximum number of locals for function / method body
-max-locals=30
-
-# Maximum number of return / yield for function / method body
-max-returns=12
-
-# Maximum number of branch for function / method body
-max-branchs=30
-
-# Maximum number of statements in function / method body
-max-statements=60
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=20
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=0
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-# checks for
-# * external modules dependencies
-# * relative / wildcard imports
-# * cyclic imports
-# * uses of deprecated modules
-# 
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report R0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report R0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report R0402 must
-# not be disabled)
-int-import-graph=
-
-
-# checks for :
-# * methods without self as first argument
-# * overridden methods signature
-# * access only to existant members via self
-# * attributes not defined in the __init__ method
-# * supported interfaces implementation
-# * unreachable code
-# 
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-
-# checks for similarities and duplicated code. This computation may be
-# memory / CPU intensive, so you should disable it if you experiments some
-# problems.
-# 
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=10
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-
-# checks for:
-# * warning notes in the code like FIXME, XXX
-# * PEP 263: source code with non ascii character but no encoding declaration
-# 
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-# checks for :
-# * unauthorized constructions
-# * strict indentation
-# * line length
-# * use of <> instead of !=
-# 
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=90
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string='    '

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/setup.cfg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/setup.cfg b/ambari-common/src/main/python/jinja2/setup.cfg
deleted file mode 100644
index 2d74c58..0000000
--- a/ambari-common/src/main/python/jinja2/setup.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-[egg_info]
-tag_build = dev
-tag_date = true
-
-[aliases]
-release = egg_info -RDb ''

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/setup.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/setup.py b/ambari-common/src/main/python/jinja2/setup.py
deleted file mode 100644
index 7956d19..0000000
--- a/ambari-common/src/main/python/jinja2/setup.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Jinja2
-~~~~~~
-
-Jinja2 is a template engine written in pure Python.  It provides a
-`Django`_ inspired non-XML syntax but supports inline expressions and
-an optional `sandboxed`_ environment.
-
-Nutshell
---------
-
-Here a small example of a Jinja template::
-
-    {% extends 'base.html' %}
-    {% block title %}Memberlist{% endblock %}
-    {% block content %}
-      <ul>
-      {% for user in users %}
-        <li><a href="{{ user.url }}">{{ user.username }}</a></li>
-      {% endfor %}
-      </ul>
-    {% endblock %}
-
-Philosophy
-----------
-
-Application logic is for the controller but don't try to make the life
-for the template designer too hard by giving him too few functionality.
-
-For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
-
-.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security)
-.. _Django: http://www.djangoproject.com/
-.. _Jinja2 webpage: http://jinja.pocoo.org/
-.. _documentation: http://jinja.pocoo.org/2/documentation/
-"""
-import sys
-
-from setuptools import setup, Extension, Feature
-
-debugsupport = Feature(
-    'optional C debug support',
-    standard=False,
-    ext_modules = [
-        Extension('jinja2._debugsupport', ['jinja2/_debugsupport.c']),
-    ],
-)
-
-
-# tell distribute to use 2to3 with our own fixers.
-extra = {}
-if sys.version_info >= (3, 0):
-    extra.update(
-        use_2to3=True,
-        use_2to3_fixers=['custom_fixers']
-    )
-
-# ignore the old '--with-speedups' flag
-try:
-    speedups_pos = sys.argv.index('--with-speedups')
-except ValueError:
-    pass
-else:
-    sys.argv[speedups_pos] = '--with-debugsupport'
-    sys.stderr.write('*' * 74 + '\n')
-    sys.stderr.write('WARNING:\n')
-    sys.stderr.write('  the --with-speedups flag is deprecated, assuming '
-                     '--with-debugsupport\n')
-    sys.stderr.write('  For the actual speedups install the MarkupSafe '
-                     'package.\n')
-    sys.stderr.write('*' * 74 + '\n')
-
-
-setup(
-    name='Jinja2',
-    version='2.5.5',
-    url='http://jinja.pocoo.org/',
-    license='BSD',
-    author='Armin Ronacher',
-    author_email='armin.ronacher@active-4.com',
-    description='A small but fast and easy to use stand-alone template '
-                'engine written in pure python.',
-    long_description=__doc__,
-    # jinja is egg safe. But we hate eggs
-    zip_safe=False,
-    classifiers=[
-        'Development Status :: 5 - Production/Stable',
-        'Environment :: Web Environment',
-        'Intended Audience :: Developers',
-        'License :: OSI Approved :: BSD License',
-        'Operating System :: OS Independent',
-        'Programming Language :: Python',
-        'Programming Language :: Python :: 3',
-        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
-        'Topic :: Software Development :: Libraries :: Python Modules',
-        'Topic :: Text Processing :: Markup :: HTML'
-    ],
-    packages=['jinja2', 'jinja2.testsuite', 'jinja2.testsuite.res',
-              'jinja2._markupsafe'],
-    extras_require={'i18n': ['Babel>=0.8']},
-    test_suite='jinja2.testsuite.suite',
-    include_package_data=True,
-    entry_points="""
-    [babel.extractors]
-    jinja2 = jinja2.ext:babel_extract[i18n]
-    """,
-    features={'debugsupport': debugsupport},
-    **extra
-)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/resource_management/core/source.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/core/source.py b/ambari-common/src/main/python/resource_management/core/source.py
index c2a4c24..22e1c6d 100644
--- a/ambari-common/src/main/python/resource_management/core/source.py
+++ b/ambari-common/src/main/python/resource_management/core/source.py
@@ -72,7 +72,7 @@ class StaticFile(Source):
 
 
 try:
-  from jinja2 import Environment as JinjaEnvironment, BaseLoader, TemplateNotFound, FunctionLoader, StrictUndefined
+  from ambari_jinja2 import Environment as JinjaEnvironment, BaseLoader, TemplateNotFound, FunctionLoader, StrictUndefined
 except ImportError:
   class Template(Source):
     def __init__(self, name, variables=None, env=None):

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index d7d2491..e6c2546 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -955,7 +955,7 @@
                 <argument>${custom.tests}</argument>
               </arguments>
               <environmentVariables>
-                  <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python:${project.basedir}/../ambari-agent/src/main/python:${project.basedir}/../ambari-common/src/main/python/jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/src/main/python:${project.basedir}/src/main/python/ambari-server-state:${project.basedir}/src/test/python:$PYTHONPATH</PYTHONPATH>
+                  <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python:${project.basedir}/../ambari-agent/src/main/python:${project.basedir}/../ambari-common/src/main/python/ambari_jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/src/main/python:${project.basedir}/src/main/python/ambari-server-state:${project.basedir}/src/test/python:$PYTHONPATH</PYTHONPATH>
               </environmentVariables>
               <skip>${skipTests}</skip>
             </configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-server/src/test/python/unitTests.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/unitTests.py b/ambari-server/src/test/python/unitTests.py
index ab99cce..773a698 100644
--- a/ambari-server/src/test/python/unitTests.py
+++ b/ambari-server/src/test/python/unitTests.py
@@ -117,7 +117,7 @@ def main():
   ambari_agent_folder = os.path.join(ambari_server_folder,"../ambari-agent")
   ambari_common_folder = os.path.join(ambari_server_folder,"../ambari-common")
   sys.path.append(ambari_common_folder + "/src/main/python")
-  sys.path.append(ambari_common_folder + "/src/main/python/jinja2")
+  sys.path.append(ambari_common_folder + "/src/main/python/ambari_jinja2")
   sys.path.append(ambari_common_folder + "/src/main/python")
   sys.path.append(ambari_common_folder + "/src/test/python")
   sys.path.append(ambari_agent_folder + "/src/main/python")

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index bf62fd2..cb47889 100644
--- a/pom.xml
+++ b/pom.xml
@@ -184,6 +184,7 @@
             <!--IDE and GIT files-->
             <exclude>.idea/</exclude>
             <exclude>.git/</exclude>
+            <exclude>.pydevproject</exclude>
             <exclude>**/.gitignore</exclude>
             <exclude>**/.gitattributes</exclude>
             <exclude>**/.gitkeep</exclude>
@@ -204,6 +205,7 @@
             <!--Python Mock library (BSD license)-->
             <exclude>ambari-common/src/test/python/mock/**</exclude>
             <!--Jinja2 library (BSD license)-->
+            <exclude>ambari-common/src/main/python/ambari_jinja2/**</exclude>
             <exclude>ambari-common/src/main/python/jinja2/**</exclude>
 
             <!--Contributions-->


[25/59] [abbrv] git commit: AMBARI-7142. Configs: missing cursor pointer on dismiss.(XI WANG)

Posted by nc...@apache.org.
AMBARI-7142. Configs: missing cursor pointer on dismiss.(XI WANG)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b68d3fab
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b68d3fab
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b68d3fab

Branch: refs/heads/branch-alerts-dev
Commit: b68d3fabbd893cbcc4dad5ad0b39e78a26d86355
Parents: dc269bb
Author: Xi Wang <xi...@apache.org>
Authored: Wed Sep 3 16:26:00 2014 -0700
Committer: Xi Wang <xi...@apache.org>
Committed: Wed Sep 3 17:17:56 2014 -0700

----------------------------------------------------------------------
 ambari-web/app/styles/application.less | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b68d3fab/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 183106e..5160eb6 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -5104,9 +5104,10 @@ ul.inline li {
 
     .icon-remove-circle {
       color: #ffffff;
-      padding-left: 10px;
-      padding-top: 7px;
+      margin-left: 10px;
+      margin-top: 0px;
       display: inline-block;
+      cursor: pointer;
     }
     .label-wrapper {
       line-height: 30px;


[05/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/environment.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/environment.py b/ambari-common/src/main/python/jinja2/jinja2/environment.py
new file mode 100644
index 0000000..ac74a5c
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/environment.py
@@ -0,0 +1,1118 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.environment
+    ~~~~~~~~~~~~~~~~~~
+
+    Provides a class that holds runtime and parsing time options.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+from jinja2 import nodes
+from jinja2.defaults import *
+from jinja2.lexer import get_lexer, TokenStream
+from jinja2.parser import Parser
+from jinja2.optimizer import optimize
+from jinja2.compiler import generate
+from jinja2.runtime import Undefined, new_context
+from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
+     TemplatesNotFound
+from jinja2.utils import import_string, LRUCache, Markup, missing, \
+     concat, consume, internalcode, _encode_filename
+
+
+# for direct template usage we have up to ten living environments
+_spontaneous_environments = LRUCache(10)
+
+# the function to create jinja traceback objects.  This is dynamically
+# imported on the first exception in the exception handler.
+_make_traceback = None
+
+
+def get_spontaneous_environment(*args):
+    """Return a new spontaneous environment.  A spontaneous environment is an
+    unnamed and unaccessible (in theory) environment that is used for
+    templates generated from a string and not from the file system.
+    """
+    try:
+        env = _spontaneous_environments.get(args)
+    except TypeError:
+        return Environment(*args)
+    if env is not None:
+        return env
+    _spontaneous_environments[args] = env = Environment(*args)
+    env.shared = True
+    return env
+
+
+def create_cache(size):
+    """Return the cache class for the given size."""
+    if size == 0:
+        return None
+    if size < 0:
+        return {}
+    return LRUCache(size)
+
+
+def copy_cache(cache):
+    """Create an empty copy of the given cache."""
+    if cache is None:
+        return None
+    elif type(cache) is dict:
+        return {}
+    return LRUCache(cache.capacity)
+
+
+def load_extensions(environment, extensions):
+    """Load the extensions from the list and bind it to the environment.
+    Returns a dict of instanciated environments.
+    """
+    result = {}
+    for extension in extensions:
+        if isinstance(extension, basestring):
+            extension = import_string(extension)
+        result[extension.identifier] = extension(environment)
+    return result
+
+
+def _environment_sanity_check(environment):
+    """Perform a sanity check on the environment."""
+    assert issubclass(environment.undefined, Undefined), 'undefined must ' \
+           'be a subclass of undefined because filters depend on it.'
+    assert environment.block_start_string != \
+           environment.variable_start_string != \
+           environment.comment_start_string, 'block, variable and comment ' \
+           'start strings must be different'
+    assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
+           'newline_sequence set to unknown line ending string.'
+    return environment
+
+
+class Environment(object):
+    r"""The core component of Jinja is the `Environment`.  It contains
+    important shared variables like configuration, filters, tests,
+    globals and others.  Instances of this class may be modified if
+    they are not shared and if no template was loaded so far.
+    Modifications on environments after the first template was loaded
+    will lead to surprising effects and undefined behavior.
+
+    Here the possible initialization parameters:
+
+        `block_start_string`
+            The string marking the begin of a block.  Defaults to ``'{%'``.
+
+        `block_end_string`
+            The string marking the end of a block.  Defaults to ``'%}'``.
+
+        `variable_start_string`
+            The string marking the begin of a print statement.
+            Defaults to ``'{{'``.
+
+        `variable_end_string`
+            The string marking the end of a print statement.  Defaults to
+            ``'}}'``.
+
+        `comment_start_string`
+            The string marking the begin of a comment.  Defaults to ``'{#'``.
+
+        `comment_end_string`
+            The string marking the end of a comment.  Defaults to ``'#}'``.
+
+        `line_statement_prefix`
+            If given and a string, this will be used as prefix for line based
+            statements.  See also :ref:`line-statements`.
+
+        `line_comment_prefix`
+            If given and a string, this will be used as prefix for line based
+            based comments.  See also :ref:`line-statements`.
+
+            .. versionadded:: 2.2
+
+        `trim_blocks`
+            If this is set to ``True`` the first newline after a block is
+            removed (block, not variable tag!).  Defaults to `False`.
+
+        `newline_sequence`
+            The sequence that starts a newline.  Must be one of ``'\r'``,
+            ``'\n'`` or ``'\r\n'``.  The default is ``'\n'`` which is a
+            useful default for Linux and OS X systems as well as web
+            applications.
+
+        `extensions`
+            List of Jinja extensions to use.  This can either be import paths
+            as strings or extension classes.  For more information have a
+            look at :ref:`the extensions documentation <jinja-extensions>`.
+
+        `optimized`
+            should the optimizer be enabled?  Default is `True`.
+
+        `undefined`
+            :class:`Undefined` or a subclass of it that is used to represent
+            undefined values in the template.
+
+        `finalize`
+            A callable that can be used to process the result of a variable
+            expression before it is output.  For example one can convert
+            `None` implicitly into an empty string here.
+
+        `autoescape`
+            If set to true the XML/HTML autoescaping feature is enabled by
+            default.  For more details about auto escaping see
+            :class:`~jinja2.utils.Markup`.  As of Jinja 2.4 this can also
+            be a callable that is passed the template name and has to
+            return `True` or `False` depending on autoescape should be
+            enabled by default.
+
+            .. versionchanged:: 2.4
+               `autoescape` can now be a function
+
+        `loader`
+            The template loader for this environment.
+
+        `cache_size`
+            The size of the cache.  Per default this is ``50`` which means
+            that if more than 50 templates are loaded the loader will clean
+            out the least recently used template.  If the cache size is set to
+            ``0`` templates are recompiled all the time, if the cache size is
+            ``-1`` the cache will not be cleaned.
+
+        `auto_reload`
+            Some loaders load templates from locations where the template
+            sources may change (ie: file system or database).  If
+            `auto_reload` is set to `True` (default) every time a template is
+            requested the loader checks if the source changed and if yes, it
+            will reload the template.  For higher performance it's possible to
+            disable that.
+
+        `bytecode_cache`
+            If set to a bytecode cache object, this object will provide a
+            cache for the internal Jinja bytecode so that templates don't
+            have to be parsed if they were not changed.
+
+            See :ref:`bytecode-cache` for more information.
+    """
+
+    #: if this environment is sandboxed.  Modifying this variable won't make
+    #: the environment sandboxed though.  For a real sandboxed environment
+    #: have a look at jinja2.sandbox
+    sandboxed = False
+
+    #: True if the environment is just an overlay
+    overlayed = False
+
+    #: the environment this environment is linked to if it is an overlay
+    linked_to = None
+
+    #: shared environments have this set to `True`.  A shared environment
+    #: must not be modified
+    shared = False
+
+    #: these are currently EXPERIMENTAL undocumented features.
+    exception_handler = None
+    exception_formatter = None
+
+    def __init__(self,
+                 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,
+                 line_statement_prefix=LINE_STATEMENT_PREFIX,
+                 line_comment_prefix=LINE_COMMENT_PREFIX,
+                 trim_blocks=TRIM_BLOCKS,
+                 newline_sequence=NEWLINE_SEQUENCE,
+                 extensions=(),
+                 optimized=True,
+                 undefined=Undefined,
+                 finalize=None,
+                 autoescape=False,
+                 loader=None,
+                 cache_size=50,
+                 auto_reload=True,
+                 bytecode_cache=None):
+        # !!Important notice!!
+        #   The constructor accepts quite a few arguments that should be
+        #   passed by keyword rather than position.  However it's important to
+        #   not change the order of arguments because it's used at least
+        #   internally in those cases:
+        #       -   spontaneus environments (i18n extension and Template)
+        #       -   unittests
+        #   If parameter changes are required only add parameters at the end
+        #   and don't change the arguments (or the defaults!) of the arguments
+        #   existing already.
+
+        # lexer / parser information
+        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.line_statement_prefix = line_statement_prefix
+        self.line_comment_prefix = line_comment_prefix
+        self.trim_blocks = trim_blocks
+        self.newline_sequence = newline_sequence
+
+        # runtime information
+        self.undefined = undefined
+        self.optimized = optimized
+        self.finalize = finalize
+        self.autoescape = autoescape
+
+        # defaults
+        self.filters = DEFAULT_FILTERS.copy()
+        self.tests = DEFAULT_TESTS.copy()
+        self.globals = DEFAULT_NAMESPACE.copy()
+
+        # set the loader provided
+        self.loader = loader
+        self.bytecode_cache = None
+        self.cache = create_cache(cache_size)
+        self.bytecode_cache = bytecode_cache
+        self.auto_reload = auto_reload
+
+        # load extensions
+        self.extensions = load_extensions(self, extensions)
+
+        _environment_sanity_check(self)
+
+    def add_extension(self, extension):
+        """Adds an extension after the environment was created.
+
+        .. versionadded:: 2.5
+        """
+        self.extensions.update(load_extensions(self, [extension]))
+
+    def extend(self, **attributes):
+        """Add the items to the instance of the environment if they do not exist
+        yet.  This is used by :ref:`extensions <writing-extensions>` to register
+        callbacks and configuration values without breaking inheritance.
+        """
+        for key, value in attributes.iteritems():
+            if not hasattr(self, key):
+                setattr(self, key, value)
+
+    def overlay(self, block_start_string=missing, block_end_string=missing,
+                variable_start_string=missing, variable_end_string=missing,
+                comment_start_string=missing, comment_end_string=missing,
+                line_statement_prefix=missing, line_comment_prefix=missing,
+                trim_blocks=missing, extensions=missing, optimized=missing,
+                undefined=missing, finalize=missing, autoescape=missing,
+                loader=missing, cache_size=missing, auto_reload=missing,
+                bytecode_cache=missing):
+        """Create a new overlay environment that shares all the data with the
+        current environment except of cache and the overridden attributes.
+        Extensions cannot be removed for an overlayed environment.  An overlayed
+        environment automatically gets all the extensions of the environment it
+        is linked to plus optional extra extensions.
+
+        Creating overlays should happen after the initial environment was set
+        up completely.  Not all attributes are truly linked, some are just
+        copied over so modifications on the original environment may not shine
+        through.
+        """
+        args = dict(locals())
+        del args['self'], args['cache_size'], args['extensions']
+
+        rv = object.__new__(self.__class__)
+        rv.__dict__.update(self.__dict__)
+        rv.overlayed = True
+        rv.linked_to = self
+
+        for key, value in args.iteritems():
+            if value is not missing:
+                setattr(rv, key, value)
+
+        if cache_size is not missing:
+            rv.cache = create_cache(cache_size)
+        else:
+            rv.cache = copy_cache(self.cache)
+
+        rv.extensions = {}
+        for key, value in self.extensions.iteritems():
+            rv.extensions[key] = value.bind(rv)
+        if extensions is not missing:
+            rv.extensions.update(load_extensions(rv, extensions))
+
+        return _environment_sanity_check(rv)
+
+    lexer = property(get_lexer, doc="The lexer for this environment.")
+
+    def iter_extensions(self):
+        """Iterates over the extensions by priority."""
+        return iter(sorted(self.extensions.values(),
+                           key=lambda x: x.priority))
+
+    def getitem(self, obj, argument):
+        """Get an item or attribute of an object but prefer the item."""
+        try:
+            return obj[argument]
+        except (TypeError, LookupError):
+            if isinstance(argument, basestring):
+                try:
+                    attr = str(argument)
+                except:
+                    pass
+                else:
+                    try:
+                        return getattr(obj, attr)
+                    except AttributeError:
+                        pass
+            return self.undefined(obj=obj, name=argument)
+
+    def getattr(self, obj, attribute):
+        """Get an item or attribute of an object but prefer the attribute.
+        Unlike :meth:`getitem` the attribute *must* be a bytestring.
+        """
+        try:
+            return getattr(obj, attribute)
+        except AttributeError:
+            pass
+        try:
+            return obj[attribute]
+        except (TypeError, LookupError, AttributeError):
+            return self.undefined(obj=obj, name=attribute)
+
+    @internalcode
+    def parse(self, source, name=None, filename=None):
+        """Parse the sourcecode and return the abstract syntax tree.  This
+        tree of nodes is used by the compiler to convert the template into
+        executable source- or bytecode.  This is useful for debugging or to
+        extract information from templates.
+
+        If you are :ref:`developing Jinja2 extensions <writing-extensions>`
+        this gives you a good overview of the node tree generated.
+        """
+        try:
+            return self._parse(source, name, filename)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
+
+    def _parse(self, source, name, filename):
+        """Internal parsing function used by `parse` and `compile`."""
+        return Parser(self, source, name, _encode_filename(filename)).parse()
+
+    def lex(self, source, name=None, filename=None):
+        """Lex the given sourcecode and return a generator that yields
+        tokens as tuples in the form ``(lineno, token_type, value)``.
+        This can be useful for :ref:`extension development <writing-extensions>`
+        and debugging templates.
+
+        This does not perform preprocessing.  If you want the preprocessing
+        of the extensions to be applied you have to filter source through
+        the :meth:`preprocess` method.
+        """
+        source = unicode(source)
+        try:
+            return self.lexer.tokeniter(source, name, filename)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
+
+    def preprocess(self, source, name=None, filename=None):
+        """Preprocesses the source with all extensions.  This is automatically
+        called for all parsing and compiling methods but *not* for :meth:`lex`
+        because there you usually only want the actual source tokenized.
+        """
+        return reduce(lambda s, e: e.preprocess(s, name, filename),
+                      self.iter_extensions(), unicode(source))
+
+    def _tokenize(self, source, name, filename=None, state=None):
+        """Called by the parser to do the preprocessing and filtering
+        for all the extensions.  Returns a :class:`~jinja2.lexer.TokenStream`.
+        """
+        source = self.preprocess(source, name, filename)
+        stream = self.lexer.tokenize(source, name, filename, state)
+        for ext in self.iter_extensions():
+            stream = ext.filter_stream(stream)
+            if not isinstance(stream, TokenStream):
+                stream = TokenStream(stream, name, filename)
+        return stream
+
+    def _generate(self, source, name, filename, defer_init=False):
+        """Internal hook that can be overriden to hook a different generate
+        method in.
+
+        .. versionadded:: 2.5
+        """
+        return generate(source, self, name, filename, defer_init=defer_init)
+
+    def _compile(self, source, filename):
+        """Internal hook that can be overriden to hook a different compile
+        method in.
+
+        .. versionadded:: 2.5
+        """
+        return compile(source, filename, 'exec')
+
+    @internalcode
+    def compile(self, source, name=None, filename=None, raw=False,
+                defer_init=False):
+        """Compile a node or template source code.  The `name` parameter is
+        the load name of the template after it was joined using
+        :meth:`join_path` if necessary, not the filename on the file system.
+        the `filename` parameter is the estimated filename of the template on
+        the file system.  If the template came from a database or memory this
+        can be omitted.
+
+        The return value of this method is a python code object.  If the `raw`
+        parameter is `True` the return value will be a string with python
+        code equivalent to the bytecode returned otherwise.  This method is
+        mainly used internally.
+
+        `defer_init` is use internally to aid the module code generator.  This
+        causes the generated code to be able to import without the global
+        environment variable to be set.
+
+        .. versionadded:: 2.4
+           `defer_init` parameter added.
+        """
+        source_hint = None
+        try:
+            if isinstance(source, basestring):
+                source_hint = source
+                source = self._parse(source, name, filename)
+            if self.optimized:
+                source = optimize(source, self)
+            source = self._generate(source, name, filename,
+                                    defer_init=defer_init)
+            if raw:
+                return source
+            if filename is None:
+                filename = '<template>'
+            else:
+                filename = _encode_filename(filename)
+            return self._compile(source, filename)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
+
+    def compile_expression(self, source, undefined_to_none=True):
+        """A handy helper method that returns a callable that accepts keyword
+        arguments that appear as variables in the expression.  If called it
+        returns the result of the expression.
+
+        This is useful if applications want to use the same rules as Jinja
+        in template "configuration files" or similar situations.
+
+        Example usage:
+
+        >>> env = Environment()
+        >>> expr = env.compile_expression('foo == 42')
+        >>> expr(foo=23)
+        False
+        >>> expr(foo=42)
+        True
+
+        Per default the return value is converted to `None` if the
+        expression returns an undefined value.  This can be changed
+        by setting `undefined_to_none` to `False`.
+
+        >>> env.compile_expression('var')() is None
+        True
+        >>> env.compile_expression('var', undefined_to_none=False)()
+        Undefined
+
+        .. versionadded:: 2.1
+        """
+        parser = Parser(self, source, state='variable')
+        exc_info = None
+        try:
+            expr = parser.parse_expression()
+            if not parser.stream.eos:
+                raise TemplateSyntaxError('chunk after expression',
+                                          parser.stream.current.lineno,
+                                          None, None)
+            expr.set_environment(self)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        if exc_info is not None:
+            self.handle_exception(exc_info, source_hint=source)
+        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
+        template = self.from_string(nodes.Template(body, lineno=1))
+        return TemplateExpression(template, undefined_to_none)
+
+    def compile_templates(self, target, extensions=None, filter_func=None,
+                          zip='deflated', log_function=None,
+                          ignore_errors=True, py_compile=False):
+        """Compiles all the templates the loader can find, compiles them
+        and stores them in `target`.  If `zip` is `None`, instead of in a
+        zipfile, the templates will be will be stored in a directory.
+        By default a deflate zip algorithm is used, to switch to
+        the stored algorithm, `zip` can be set to ``'stored'``.
+
+        `extensions` and `filter_func` are passed to :meth:`list_templates`.
+        Each template returned will be compiled to the target folder or
+        zipfile.
+
+        By default template compilation errors are ignored.  In case a
+        log function is provided, errors are logged.  If you want template
+        syntax errors to abort the compilation you can set `ignore_errors`
+        to `False` and you will get an exception on syntax errors.
+
+        If `py_compile` is set to `True` .pyc files will be written to the
+        target instead of standard .py files.
+
+        .. versionadded:: 2.4
+        """
+        from jinja2.loaders import ModuleLoader
+
+        if log_function is None:
+            log_function = lambda x: None
+
+        if py_compile:
+            import imp, struct, marshal
+            py_header = imp.get_magic() + \
+                u'\xff\xff\xff\xff'.encode('iso-8859-15')
+
+        def write_file(filename, data, mode):
+            if zip:
+                info = ZipInfo(filename)
+                info.external_attr = 0755 << 16L
+                zip_file.writestr(info, data)
+            else:
+                f = open(os.path.join(target, filename), mode)
+                try:
+                    f.write(data)
+                finally:
+                    f.close()
+
+        if zip is not None:
+            from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
+            zip_file = ZipFile(target, 'w', dict(deflated=ZIP_DEFLATED,
+                                                 stored=ZIP_STORED)[zip])
+            log_function('Compiling into Zip archive "%s"' % target)
+        else:
+            if not os.path.isdir(target):
+                os.makedirs(target)
+            log_function('Compiling into folder "%s"' % target)
+
+        try:
+            for name in self.list_templates(extensions, filter_func):
+                source, filename, _ = self.loader.get_source(self, name)
+                try:
+                    code = self.compile(source, name, filename, True, True)
+                except TemplateSyntaxError, e:
+                    if not ignore_errors:
+                        raise
+                    log_function('Could not compile "%s": %s' % (name, e))
+                    continue
+
+                filename = ModuleLoader.get_module_filename(name)
+
+                if py_compile:
+                    c = self._compile(code, _encode_filename(filename))
+                    write_file(filename + 'c', py_header +
+                               marshal.dumps(c), 'wb')
+                    log_function('Byte-compiled "%s" as %s' %
+                                 (name, filename + 'c'))
+                else:
+                    write_file(filename, code, 'w')
+                    log_function('Compiled "%s" as %s' % (name, filename))
+        finally:
+            if zip:
+                zip_file.close()
+
+        log_function('Finished compiling templates')
+
+    def list_templates(self, extensions=None, filter_func=None):
+        """Returns a list of templates for this environment.  This requires
+        that the loader supports the loader's
+        :meth:`~BaseLoader.list_templates` method.
+
+        If there are other files in the template folder besides the
+        actual templates, the returned list can be filtered.  There are two
+        ways: either `extensions` is set to a list of file extensions for
+        templates, or a `filter_func` can be provided which is a callable that
+        is passed a template name and should return `True` if it should end up
+        in the result list.
+
+        If the loader does not support that, a :exc:`TypeError` is raised.
+        """
+        x = self.loader.list_templates()
+        if extensions is not None:
+            if filter_func is not None:
+                raise TypeError('either extensions or filter_func '
+                                'can be passed, but not both')
+            filter_func = lambda x: '.' in x and \
+                                    x.rsplit('.', 1)[1] in extensions
+        if filter_func is not None:
+            x = filter(filter_func, x)
+        return x
+
+    def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
+        """Exception handling helper.  This is used internally to either raise
+        rewritten exceptions or return a rendered traceback for the template.
+        """
+        global _make_traceback
+        if exc_info is None:
+            exc_info = sys.exc_info()
+
+        # the debugging module is imported when it's used for the first time.
+        # we're doing a lot of stuff there and for applications that do not
+        # get any exceptions in template rendering there is no need to load
+        # all of that.
+        if _make_traceback is None:
+            from jinja2.debug import make_traceback as _make_traceback
+        traceback = _make_traceback(exc_info, source_hint)
+        if rendered and self.exception_formatter is not None:
+            return self.exception_formatter(traceback)
+        if self.exception_handler is not None:
+            self.exception_handler(traceback)
+        exc_type, exc_value, tb = traceback.standard_exc_info
+        raise exc_type, exc_value, tb
+
+    def join_path(self, template, parent):
+        """Join a template with the parent.  By default all the lookups are
+        relative to the loader root so this method returns the `template`
+        parameter unchanged, but if the paths should be relative to the
+        parent template, this function can be used to calculate the real
+        template name.
+
+        Subclasses may override this method and implement template path
+        joining here.
+        """
+        return template
+
+    @internalcode
+    def _load_template(self, name, globals):
+        if self.loader is None:
+            raise TypeError('no loader for this environment specified')
+        if self.cache is not None:
+            template = self.cache.get(name)
+            if template is not None and (not self.auto_reload or \
+                                         template.is_up_to_date):
+                return template
+        template = self.loader.load(self, name, globals)
+        if self.cache is not None:
+            self.cache[name] = template
+        return template
+
+    @internalcode
+    def get_template(self, name, parent=None, globals=None):
+        """Load a template from the loader.  If a loader is configured this
+        method ask the loader for the template and returns a :class:`Template`.
+        If the `parent` parameter is not `None`, :meth:`join_path` is called
+        to get the real template name before loading.
+
+        The `globals` parameter can be used to provide template wide globals.
+        These variables are available in the context at render time.
+
+        If the template does not exist a :exc:`TemplateNotFound` exception is
+        raised.
+
+        .. versionchanged:: 2.4
+           If `name` is a :class:`Template` object it is returned from the
+           function unchanged.
+        """
+        if isinstance(name, Template):
+            return name
+        if parent is not None:
+            name = self.join_path(name, parent)
+        return self._load_template(name, self.make_globals(globals))
+
+    @internalcode
+    def select_template(self, names, parent=None, globals=None):
+        """Works like :meth:`get_template` but tries a number of templates
+        before it fails.  If it cannot find any of the templates, it will
+        raise a :exc:`TemplatesNotFound` exception.
+
+        .. versionadded:: 2.3
+
+        .. versionchanged:: 2.4
+           If `names` contains a :class:`Template` object it is returned
+           from the function unchanged.
+        """
+        if not names:
+            raise TemplatesNotFound(message=u'Tried to select from an empty list '
+                                            u'of templates.')
+        globals = self.make_globals(globals)
+        for name in names:
+            if isinstance(name, Template):
+                return name
+            if parent is not None:
+                name = self.join_path(name, parent)
+            try:
+                return self._load_template(name, globals)
+            except TemplateNotFound:
+                pass
+        raise TemplatesNotFound(names)
+
+    @internalcode
+    def get_or_select_template(self, template_name_or_list,
+                               parent=None, globals=None):
+        """Does a typecheck and dispatches to :meth:`select_template`
+        if an iterable of template names is given, otherwise to
+        :meth:`get_template`.
+
+        .. versionadded:: 2.3
+        """
+        if isinstance(template_name_or_list, basestring):
+            return self.get_template(template_name_or_list, parent, globals)
+        elif isinstance(template_name_or_list, Template):
+            return template_name_or_list
+        return self.select_template(template_name_or_list, parent, globals)
+
+    def from_string(self, source, globals=None, template_class=None):
+        """Load a template from a string.  This parses the source given and
+        returns a :class:`Template` object.
+        """
+        globals = self.make_globals(globals)
+        cls = template_class or self.template_class
+        return cls.from_code(self, self.compile(source), globals, None)
+
+    def make_globals(self, d):
+        """Return a dict for the globals."""
+        if not d:
+            return self.globals
+        return dict(self.globals, **d)
+
+
+class Template(object):
+    """The central template object.  This class represents a compiled template
+    and is used to evaluate it.
+
+    Normally the template object is generated from an :class:`Environment` but
+    it also has a constructor that makes it possible to create a template
+    instance directly using the constructor.  It takes the same arguments as
+    the environment constructor but it's not possible to specify a loader.
+
+    Every template object has a few methods and members that are guaranteed
+    to exist.  However it's important that a template object should be
+    considered immutable.  Modifications on the object are not supported.
+
+    Template objects created from the constructor rather than an environment
+    do have an `environment` attribute that points to a temporary environment
+    that is probably shared with other templates created with the constructor
+    and compatible settings.
+
+    >>> template = Template('Hello {{ name }}!')
+    >>> template.render(name='John Doe')
+    u'Hello John Doe!'
+
+    >>> stream = template.stream(name='John Doe')
+    >>> stream.next()
+    u'Hello John Doe!'
+    >>> stream.next()
+    Traceback (most recent call last):
+        ...
+    StopIteration
+    """
+
+    def __new__(cls, source,
+                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,
+                line_statement_prefix=LINE_STATEMENT_PREFIX,
+                line_comment_prefix=LINE_COMMENT_PREFIX,
+                trim_blocks=TRIM_BLOCKS,
+                newline_sequence=NEWLINE_SEQUENCE,
+                extensions=(),
+                optimized=True,
+                undefined=Undefined,
+                finalize=None,
+                autoescape=False):
+        env = get_spontaneous_environment(
+            block_start_string, block_end_string, variable_start_string,
+            variable_end_string, comment_start_string, comment_end_string,
+            line_statement_prefix, line_comment_prefix, trim_blocks,
+            newline_sequence, frozenset(extensions), optimized, undefined,
+            finalize, autoescape, None, 0, False, None)
+        return env.from_string(source, template_class=cls)
+
+    @classmethod
+    def from_code(cls, environment, code, globals, uptodate=None):
+        """Creates a template object from compiled code and the globals.  This
+        is used by the loaders and environment to create a template object.
+        """
+        namespace = {
+            'environment':  environment,
+            '__file__':     code.co_filename
+        }
+        exec code in namespace
+        rv = cls._from_namespace(environment, namespace, globals)
+        rv._uptodate = uptodate
+        return rv
+
+    @classmethod
+    def from_module_dict(cls, environment, module_dict, globals):
+        """Creates a template object from a module.  This is used by the
+        module loader to create a template object.
+
+        .. versionadded:: 2.4
+        """
+        return cls._from_namespace(environment, module_dict, globals)
+
+    @classmethod
+    def _from_namespace(cls, environment, namespace, globals):
+        t = object.__new__(cls)
+        t.environment = environment
+        t.globals = globals
+        t.name = namespace['name']
+        t.filename = namespace['__file__']
+        t.blocks = namespace['blocks']
+
+        # render function and module
+        t.root_render_func = namespace['root']
+        t._module = None
+
+        # debug and loader helpers
+        t._debug_info = namespace['debug_info']
+        t._uptodate = None
+
+        # store the reference
+        namespace['environment'] = environment
+        namespace['__jinja_template__'] = t
+
+        return t
+
+    def render(self, *args, **kwargs):
+        """This method accepts the same arguments as the `dict` constructor:
+        A dict, a dict subclass or some keyword arguments.  If no arguments
+        are given the context will be empty.  These two calls do the same::
+
+            template.render(knights='that say nih')
+            template.render({'knights': 'that say nih'})
+
+        This will return the rendered template as unicode string.
+        """
+        vars = dict(*args, **kwargs)
+        try:
+            return concat(self.root_render_func(self.new_context(vars)))
+        except:
+            exc_info = sys.exc_info()
+        return self.environment.handle_exception(exc_info, True)
+
+    def stream(self, *args, **kwargs):
+        """Works exactly like :meth:`generate` but returns a
+        :class:`TemplateStream`.
+        """
+        return TemplateStream(self.generate(*args, **kwargs))
+
+    def generate(self, *args, **kwargs):
+        """For very large templates it can be useful to not render the whole
+        template at once but evaluate each statement after another and yield
+        piece for piece.  This method basically does exactly that and returns
+        a generator that yields one item after another as unicode strings.
+
+        It accepts the same arguments as :meth:`render`.
+        """
+        vars = dict(*args, **kwargs)
+        try:
+            for event in self.root_render_func(self.new_context(vars)):
+                yield event
+        except:
+            exc_info = sys.exc_info()
+        else:
+            return
+        yield self.environment.handle_exception(exc_info, True)
+
+    def new_context(self, vars=None, shared=False, locals=None):
+        """Create a new :class:`Context` for this template.  The vars
+        provided will be passed to the template.  Per default the globals
+        are added to the context.  If shared is set to `True` the data
+        is passed as it to the context without adding the globals.
+
+        `locals` can be a dict of local variables for internal usage.
+        """
+        return new_context(self.environment, self.name, self.blocks,
+                           vars, shared, self.globals, locals)
+
+    def make_module(self, vars=None, shared=False, locals=None):
+        """This method works like the :attr:`module` attribute when called
+        without arguments but it will evaluate the template on every call
+        rather than caching it.  It's also possible to provide
+        a dict which is then used as context.  The arguments are the same
+        as for the :meth:`new_context` method.
+        """
+        return TemplateModule(self, self.new_context(vars, shared, locals))
+
+    @property
+    def module(self):
+        """The template as module.  This is used for imports in the
+        template runtime but is also useful if one wants to access
+        exported template variables from the Python layer:
+
+        >>> t = Template('{% macro foo() %}42{% endmacro %}23')
+        >>> unicode(t.module)
+        u'23'
+        >>> t.module.foo()
+        u'42'
+        """
+        if self._module is not None:
+            return self._module
+        self._module = rv = self.make_module()
+        return rv
+
+    def get_corresponding_lineno(self, lineno):
+        """Return the source line number of a line number in the
+        generated bytecode as they are not in sync.
+        """
+        for template_line, code_line in reversed(self.debug_info):
+            if code_line <= lineno:
+                return template_line
+        return 1
+
+    @property
+    def is_up_to_date(self):
+        """If this variable is `False` there is a newer version available."""
+        if self._uptodate is None:
+            return True
+        return self._uptodate()
+
+    @property
+    def debug_info(self):
+        """The debug info mapping."""
+        return [tuple(map(int, x.split('='))) for x in
+                self._debug_info.split('&')]
+
+    def __repr__(self):
+        if self.name is None:
+            name = 'memory:%x' % id(self)
+        else:
+            name = repr(self.name)
+        return '<%s %s>' % (self.__class__.__name__, name)
+
+
+class TemplateModule(object):
+    """Represents an imported template.  All the exported names of the
+    template are available as attributes on this object.  Additionally
+    converting it into an unicode- or bytestrings renders the contents.
+    """
+
+    def __init__(self, template, context):
+        self._body_stream = list(template.root_render_func(context))
+        self.__dict__.update(context.get_exported())
+        self.__name__ = template.name
+
+    def __html__(self):
+        return Markup(concat(self._body_stream))
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        return concat(self._body_stream)
+
+    def __repr__(self):
+        if self.__name__ is None:
+            name = 'memory:%x' % id(self)
+        else:
+            name = repr(self.__name__)
+        return '<%s %s>' % (self.__class__.__name__, name)
+
+
+class TemplateExpression(object):
+    """The :meth:`jinja2.Environment.compile_expression` method returns an
+    instance of this object.  It encapsulates the expression-like access
+    to the template with an expression it wraps.
+    """
+
+    def __init__(self, template, undefined_to_none):
+        self._template = template
+        self._undefined_to_none = undefined_to_none
+
+    def __call__(self, *args, **kwargs):
+        context = self._template.new_context(dict(*args, **kwargs))
+        consume(self._template.root_render_func(context))
+        rv = context.vars['result']
+        if self._undefined_to_none and isinstance(rv, Undefined):
+            rv = None
+        return rv
+
+
+class TemplateStream(object):
+    """A template stream works pretty much like an ordinary python generator
+    but it can buffer multiple items to reduce the number of total iterations.
+    Per default the output is unbuffered which means that for every unbuffered
+    instruction in the template one unicode string is yielded.
+
+    If buffering is enabled with a buffer size of 5, five items are combined
+    into a new unicode string.  This is mainly useful if you are streaming
+    big templates to a client via WSGI which flushes after each iteration.
+    """
+
+    def __init__(self, gen):
+        self._gen = gen
+        self.disable_buffering()
+
+    def dump(self, fp, encoding=None, errors='strict'):
+        """Dump the complete stream into a file or file-like object.
+        Per default unicode strings are written, if you want to encode
+        before writing specifiy an `encoding`.
+
+        Example usage::
+
+            Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
+        """
+        close = False
+        if isinstance(fp, basestring):
+            fp = file(fp, 'w')
+            close = True
+        try:
+            if encoding is not None:
+                iterable = (x.encode(encoding, errors) for x in self)
+            else:
+                iterable = self
+            if hasattr(fp, 'writelines'):
+                fp.writelines(iterable)
+            else:
+                for item in iterable:
+                    fp.write(item)
+        finally:
+            if close:
+                fp.close()
+
+    def disable_buffering(self):
+        """Disable the output buffering."""
+        self._next = self._gen.next
+        self.buffered = False
+
+    def enable_buffering(self, size=5):
+        """Enable buffering.  Buffer `size` items before yielding them."""
+        if size <= 1:
+            raise ValueError('buffer size too small')
+
+        def generator(next):
+            buf = []
+            c_size = 0
+            push = buf.append
+
+            while 1:
+                try:
+                    while c_size < size:
+                        c = next()
+                        push(c)
+                        if c:
+                            c_size += 1
+                except StopIteration:
+                    if not c_size:
+                        return
+                yield concat(buf)
+                del buf[:]
+                c_size = 0
+
+        self.buffered = True
+        self._next = generator(self._gen.next).next
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        return self._next()
+
+
+# hook in default template class.  if anyone reads this comment: ignore that
+# it's possible to use custom templates ;-)
+Environment.template_class = Template

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/exceptions.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/exceptions.py b/ambari-common/src/main/python/jinja2/jinja2/exceptions.py
new file mode 100644
index 0000000..771f6a8
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/exceptions.py
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.exceptions
+    ~~~~~~~~~~~~~~~~~
+
+    Jinja exceptions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+
+
+class TemplateError(Exception):
+    """Baseclass for all template errors."""
+
+    def __init__(self, message=None):
+        if message is not None:
+            message = unicode(message).encode('utf-8')
+        Exception.__init__(self, message)
+
+    @property
+    def message(self):
+        if self.args:
+            message = self.args[0]
+            if message is not None:
+                return message.decode('utf-8', 'replace')
+
+
+class TemplateNotFound(IOError, LookupError, TemplateError):
+    """Raised if a template does not exist."""
+
+    # looks weird, but removes the warning descriptor that just
+    # bogusly warns us about message being deprecated
+    message = None
+
+    def __init__(self, name, message=None):
+        IOError.__init__(self)
+        if message is None:
+            message = name
+        self.message = message
+        self.name = name
+        self.templates = [name]
+
+    def __str__(self):
+        return self.message.encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        return self.message
+
+
+class TemplatesNotFound(TemplateNotFound):
+    """Like :class:`TemplateNotFound` but raised if multiple templates
+    are selected.  This is a subclass of :class:`TemplateNotFound`
+    exception, so just catching the base exception will catch both.
+
+    .. versionadded:: 2.2
+    """
+
+    def __init__(self, names=(), message=None):
+        if message is None:
+            message = u'non of the templates given were found: ' + \
+                      u', '.join(map(unicode, names))
+        TemplateNotFound.__init__(self, names and names[-1] or None, message)
+        self.templates = list(names)
+
+
+class TemplateSyntaxError(TemplateError):
+    """Raised to tell the user that there is a problem with the template."""
+
+    def __init__(self, message, lineno, name=None, filename=None):
+        TemplateError.__init__(self, message)
+        self.lineno = lineno
+        self.name = name
+        self.filename = filename
+        self.source = None
+
+        # this is set to True if the debug.translate_syntax_error
+        # function translated the syntax error into a new traceback
+        self.translated = False
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        # for translated errors we only return the message
+        if self.translated:
+            return self.message
+
+        # otherwise attach some stuff
+        location = 'line %d' % self.lineno
+        name = self.filename or self.name
+        if name:
+            location = 'File "%s", %s' % (name, location)
+        lines = [self.message, '  ' + location]
+
+        # if the source is set, add the line to the output
+        if self.source is not None:
+            try:
+                line = self.source.splitlines()[self.lineno - 1]
+            except IndexError:
+                line = None
+            if line:
+                lines.append('    ' + line.strip())
+
+        return u'\n'.join(lines)
+
+
+class TemplateAssertionError(TemplateSyntaxError):
+    """Like a template syntax error, but covers cases where something in the
+    template caused an error at compile time that wasn't necessarily caused
+    by a syntax error.  However it's a direct subclass of
+    :exc:`TemplateSyntaxError` and has the same attributes.
+    """
+
+
+class TemplateRuntimeError(TemplateError):
+    """A generic runtime error in the template engine.  Under some situations
+    Jinja may raise this exception.
+    """
+
+
+class UndefinedError(TemplateRuntimeError):
+    """Raised if a template tries to operate on :class:`Undefined`."""
+
+
+class SecurityError(TemplateRuntimeError):
+    """Raised if a template tries to do something insecure if the
+    sandbox is enabled.
+    """
+
+
+class FilterArgumentError(TemplateRuntimeError):
+    """This error is raised if a filter was called with inappropriate
+    arguments
+    """

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/ext.py b/ambari-common/src/main/python/jinja2/jinja2/ext.py
new file mode 100644
index 0000000..ceb3895
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/ext.py
@@ -0,0 +1,610 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.ext
+    ~~~~~~~~~~
+
+    Jinja extensions allow to add custom tags similar to the way django custom
+    tags work.  By default two example extensions exist: an i18n and a cache
+    extension.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from collections import deque
+from jinja2 import nodes
+from jinja2.defaults import *
+from jinja2.environment import Environment
+from jinja2.runtime import Undefined, concat
+from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
+from jinja2.utils import contextfunction, import_string, Markup, next
+
+
+# the only real useful gettext functions for a Jinja template.  Note
+# that ugettext must be assigned to gettext as Jinja doesn't support
+# non unicode strings.
+GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext')
+
+
+class ExtensionRegistry(type):
+    """Gives the extension an unique identifier."""
+
+    def __new__(cls, name, bases, d):
+        rv = type.__new__(cls, name, bases, d)
+        rv.identifier = rv.__module__ + '.' + rv.__name__
+        return rv
+
+
+class Extension(object):
+    """Extensions can be used to add extra functionality to the Jinja template
+    system at the parser level.  Custom extensions are bound to an environment
+    but may not store environment specific data on `self`.  The reason for
+    this is that an extension can be bound to another environment (for
+    overlays) by creating a copy and reassigning the `environment` attribute.
+
+    As extensions are created by the environment they cannot accept any
+    arguments for configuration.  One may want to work around that by using
+    a factory function, but that is not possible as extensions are identified
+    by their import name.  The correct way to configure the extension is
+    storing the configuration values on the environment.  Because this way the
+    environment ends up acting as central configuration storage the
+    attributes may clash which is why extensions have to ensure that the names
+    they choose for configuration are not too generic.  ``prefix`` for example
+    is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
+    name as includes the name of the extension (fragment cache).
+    """
+    __metaclass__ = ExtensionRegistry
+
+    #: if this extension parses this is the list of tags it's listening to.
+    tags = set()
+
+    #: the priority of that extension.  This is especially useful for
+    #: extensions that preprocess values.  A lower value means higher
+    #: priority.
+    #:
+    #: .. versionadded:: 2.4
+    priority = 100
+
+    def __init__(self, environment):
+        self.environment = environment
+
+    def bind(self, environment):
+        """Create a copy of this extension bound to another environment."""
+        rv = object.__new__(self.__class__)
+        rv.__dict__.update(self.__dict__)
+        rv.environment = environment
+        return rv
+
+    def preprocess(self, source, name, filename=None):
+        """This method is called before the actual lexing and can be used to
+        preprocess the source.  The `filename` is optional.  The return value
+        must be the preprocessed source.
+        """
+        return source
+
+    def filter_stream(self, stream):
+        """It's passed a :class:`~jinja2.lexer.TokenStream` that can be used
+        to filter tokens returned.  This method has to return an iterable of
+        :class:`~jinja2.lexer.Token`\s, but it doesn't have to return a
+        :class:`~jinja2.lexer.TokenStream`.
+
+        In the `ext` folder of the Jinja2 source distribution there is a file
+        called `inlinegettext.py` which implements a filter that utilizes this
+        method.
+        """
+        return stream
+
+    def parse(self, parser):
+        """If any of the :attr:`tags` matched this method is called with the
+        parser as first argument.  The token the parser stream is pointing at
+        is the name token that matched.  This method has to return one or a
+        list of multiple nodes.
+        """
+        raise NotImplementedError()
+
+    def attr(self, name, lineno=None):
+        """Return an attribute node for the current extension.  This is useful
+        to pass constants on extensions to generated template code::
+
+            self.attr('_my_attribute', lineno=lineno)
+        """
+        return nodes.ExtensionAttribute(self.identifier, name, lineno=lineno)
+
+    def call_method(self, name, args=None, kwargs=None, dyn_args=None,
+                    dyn_kwargs=None, lineno=None):
+        """Call a method of the extension.  This is a shortcut for
+        :meth:`attr` + :class:`jinja2.nodes.Call`.
+        """
+        if args is None:
+            args = []
+        if kwargs is None:
+            kwargs = []
+        return nodes.Call(self.attr(name, lineno=lineno), args, kwargs,
+                          dyn_args, dyn_kwargs, lineno=lineno)
+
+
+@contextfunction
+def _gettext_alias(__context, *args, **kwargs):
+    return __context.call(__context.resolve('gettext'), *args, **kwargs)
+
+
+def _make_new_gettext(func):
+    @contextfunction
+    def gettext(__context, __string, **variables):
+        rv = __context.call(func, __string)
+        if __context.eval_ctx.autoescape:
+            rv = Markup(rv)
+        return rv % variables
+    return gettext
+
+
+def _make_new_ngettext(func):
+    @contextfunction
+    def ngettext(__context, __singular, __plural, __num, **variables):
+        variables.setdefault('num', __num)
+        rv = __context.call(func, __singular, __plural, __num)
+        if __context.eval_ctx.autoescape:
+            rv = Markup(rv)
+        return rv % variables
+    return ngettext
+
+
+class InternationalizationExtension(Extension):
+    """This extension adds gettext support to Jinja2."""
+    tags = set(['trans'])
+
+    # TODO: the i18n extension is currently reevaluating values in a few
+    # situations.  Take this example:
+    #   {% trans count=something() %}{{ count }} foo{% pluralize
+    #     %}{{ count }} fooss{% endtrans %}
+    # something is called twice here.  One time for the gettext value and
+    # the other time for the n-parameter of the ngettext function.
+
+    def __init__(self, environment):
+        Extension.__init__(self, environment)
+        environment.globals['_'] = _gettext_alias
+        environment.extend(
+            install_gettext_translations=self._install,
+            install_null_translations=self._install_null,
+            install_gettext_callables=self._install_callables,
+            uninstall_gettext_translations=self._uninstall,
+            extract_translations=self._extract,
+            newstyle_gettext=False
+        )
+
+    def _install(self, translations, newstyle=None):
+        gettext = getattr(translations, 'ugettext', None)
+        if gettext is None:
+            gettext = translations.gettext
+        ngettext = getattr(translations, 'ungettext', None)
+        if ngettext is None:
+            ngettext = translations.ngettext
+        self._install_callables(gettext, ngettext, newstyle)
+
+    def _install_null(self, newstyle=None):
+        self._install_callables(
+            lambda x: x,
+            lambda s, p, n: (n != 1 and (p,) or (s,))[0],
+            newstyle
+        )
+
+    def _install_callables(self, gettext, ngettext, newstyle=None):
+        if newstyle is not None:
+            self.environment.newstyle_gettext = newstyle
+        if self.environment.newstyle_gettext:
+            gettext = _make_new_gettext(gettext)
+            ngettext = _make_new_ngettext(ngettext)
+        self.environment.globals.update(
+            gettext=gettext,
+            ngettext=ngettext
+        )
+
+    def _uninstall(self, translations):
+        for key in 'gettext', 'ngettext':
+            self.environment.globals.pop(key, None)
+
+    def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
+        if isinstance(source, basestring):
+            source = self.environment.parse(source)
+        return extract_from_ast(source, gettext_functions)
+
+    def parse(self, parser):
+        """Parse a translatable tag."""
+        lineno = next(parser.stream).lineno
+        num_called_num = False
+
+        # find all the variables referenced.  Additionally a variable can be
+        # defined in the body of the trans block too, but this is checked at
+        # a later state.
+        plural_expr = None
+        variables = {}
+        while parser.stream.current.type != 'block_end':
+            if variables:
+                parser.stream.expect('comma')
+
+            # skip colon for python compatibility
+            if parser.stream.skip_if('colon'):
+                break
+
+            name = parser.stream.expect('name')
+            if name.value in variables:
+                parser.fail('translatable variable %r defined twice.' %
+                            name.value, name.lineno,
+                            exc=TemplateAssertionError)
+
+            # expressions
+            if parser.stream.current.type == 'assign':
+                next(parser.stream)
+                variables[name.value] = var = parser.parse_expression()
+            else:
+                variables[name.value] = var = nodes.Name(name.value, 'load')
+
+            if plural_expr is None:
+                plural_expr = var
+                num_called_num = name.value == 'num'
+
+        parser.stream.expect('block_end')
+
+        plural = plural_names = None
+        have_plural = False
+        referenced = set()
+
+        # now parse until endtrans or pluralize
+        singular_names, singular = self._parse_block(parser, True)
+        if singular_names:
+            referenced.update(singular_names)
+            if plural_expr is None:
+                plural_expr = nodes.Name(singular_names[0], 'load')
+                num_called_num = singular_names[0] == 'num'
+
+        # if we have a pluralize block, we parse that too
+        if parser.stream.current.test('name:pluralize'):
+            have_plural = True
+            next(parser.stream)
+            if parser.stream.current.type != 'block_end':
+                name = parser.stream.expect('name')
+                if name.value not in variables:
+                    parser.fail('unknown variable %r for pluralization' %
+                                name.value, name.lineno,
+                                exc=TemplateAssertionError)
+                plural_expr = variables[name.value]
+                num_called_num = name.value == 'num'
+            parser.stream.expect('block_end')
+            plural_names, plural = self._parse_block(parser, False)
+            next(parser.stream)
+            referenced.update(plural_names)
+        else:
+            next(parser.stream)
+
+        # register free names as simple name expressions
+        for var in referenced:
+            if var not in variables:
+                variables[var] = nodes.Name(var, 'load')
+
+        if not have_plural:
+            plural_expr = None
+        elif plural_expr is None:
+            parser.fail('pluralize without variables', lineno)
+
+        node = self._make_node(singular, plural, variables, plural_expr,
+                               bool(referenced),
+                               num_called_num and have_plural)
+        node.set_lineno(lineno)
+        return node
+
+    def _parse_block(self, parser, allow_pluralize):
+        """Parse until the next block tag with a given name."""
+        referenced = []
+        buf = []
+        while 1:
+            if parser.stream.current.type == 'data':
+                buf.append(parser.stream.current.value.replace('%', '%%'))
+                next(parser.stream)
+            elif parser.stream.current.type == 'variable_begin':
+                next(parser.stream)
+                name = parser.stream.expect('name').value
+                referenced.append(name)
+                buf.append('%%(%s)s' % name)
+                parser.stream.expect('variable_end')
+            elif parser.stream.current.type == 'block_begin':
+                next(parser.stream)
+                if parser.stream.current.test('name:endtrans'):
+                    break
+                elif parser.stream.current.test('name:pluralize'):
+                    if allow_pluralize:
+                        break
+                    parser.fail('a translatable section can have only one '
+                                'pluralize section')
+                parser.fail('control structures in translatable sections are '
+                            'not allowed')
+            elif parser.stream.eos:
+                parser.fail('unclosed translation block')
+            else:
+                assert False, 'internal parser error'
+
+        return referenced, concat(buf)
+
+    def _make_node(self, singular, plural, variables, plural_expr,
+                   vars_referenced, num_called_num):
+        """Generates a useful node from the data provided."""
+        # no variables referenced?  no need to escape for old style
+        # gettext invocations only if there are vars.
+        if not vars_referenced and not self.environment.newstyle_gettext:
+            singular = singular.replace('%%', '%')
+            if plural:
+                plural = plural.replace('%%', '%')
+
+        # singular only:
+        if plural_expr is None:
+            gettext = nodes.Name('gettext', 'load')
+            node = nodes.Call(gettext, [nodes.Const(singular)],
+                              [], None, None)
+
+        # singular and plural
+        else:
+            ngettext = nodes.Name('ngettext', 'load')
+            node = nodes.Call(ngettext, [
+                nodes.Const(singular),
+                nodes.Const(plural),
+                plural_expr
+            ], [], None, None)
+
+        # in case newstyle gettext is used, the method is powerful
+        # enough to handle the variable expansion and autoescape
+        # handling itself
+        if self.environment.newstyle_gettext:
+            for key, value in variables.iteritems():
+                # the function adds that later anyways in case num was
+                # called num, so just skip it.
+                if num_called_num and key == 'num':
+                    continue
+                node.kwargs.append(nodes.Keyword(key, value))
+
+        # otherwise do that here
+        else:
+            # mark the return value as safe if we are in an
+            # environment with autoescaping turned on
+            node = nodes.MarkSafeIfAutoescape(node)
+            if variables:
+                node = nodes.Mod(node, nodes.Dict([
+                    nodes.Pair(nodes.Const(key), value)
+                    for key, value in variables.items()
+                ]))
+        return nodes.Output([node])
+
+
+class ExprStmtExtension(Extension):
+    """Adds a `do` tag to Jinja2 that works like the print statement just
+    that it doesn't print the return value.
+    """
+    tags = set(['do'])
+
+    def parse(self, parser):
+        node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
+        node.node = parser.parse_tuple()
+        return node
+
+
+class LoopControlExtension(Extension):
+    """Adds break and continue to the template engine."""
+    tags = set(['break', 'continue'])
+
+    def parse(self, parser):
+        token = next(parser.stream)
+        if token.value == 'break':
+            return nodes.Break(lineno=token.lineno)
+        return nodes.Continue(lineno=token.lineno)
+
+
+class WithExtension(Extension):
+    """Adds support for a django-like with block."""
+    tags = set(['with'])
+
+    def parse(self, parser):
+        node = nodes.Scope(lineno=next(parser.stream).lineno)
+        assignments = []
+        while parser.stream.current.type != 'block_end':
+            lineno = parser.stream.current.lineno
+            if assignments:
+                parser.stream.expect('comma')
+            target = parser.parse_assign_target()
+            parser.stream.expect('assign')
+            expr = parser.parse_expression()
+            assignments.append(nodes.Assign(target, expr, lineno=lineno))
+        node.body = assignments + \
+            list(parser.parse_statements(('name:endwith',),
+                                         drop_needle=True))
+        return node
+
+
+class AutoEscapeExtension(Extension):
+    """Changes auto escape rules for a scope."""
+    tags = set(['autoescape'])
+
+    def parse(self, parser):
+        node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
+        node.options = [
+            nodes.Keyword('autoescape', parser.parse_expression())
+        ]
+        node.body = parser.parse_statements(('name:endautoescape',),
+                                            drop_needle=True)
+        return nodes.Scope([node])
+
+
+def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
+                     babel_style=True):
+    """Extract localizable strings from the given template node.  Per
+    default this function returns matches in babel style that means non string
+    parameters as well as keyword arguments are returned as `None`.  This
+    allows Babel to figure out what you really meant if you are using
+    gettext functions that allow keyword arguments for placeholder expansion.
+    If you don't want that behavior set the `babel_style` parameter to `False`
+    which causes only strings to be returned and parameters are always stored
+    in tuples.  As a consequence invalid gettext calls (calls without a single
+    string parameter or string parameters after non-string parameters) are
+    skipped.
+
+    This example explains the behavior:
+
+    >>> from jinja2 import Environment
+    >>> env = Environment()
+    >>> node = env.parse('{{ (_("foo"), _(), ngettext("foo", "bar", 42)) }}')
+    >>> list(extract_from_ast(node))
+    [(1, '_', 'foo'), (1, '_', ()), (1, 'ngettext', ('foo', 'bar', None))]
+    >>> list(extract_from_ast(node, babel_style=False))
+    [(1, '_', ('foo',)), (1, 'ngettext', ('foo', 'bar'))]
+
+    For every string found this function yields a ``(lineno, function,
+    message)`` tuple, where:
+
+    * ``lineno`` is the number of the line on which the string was found,
+    * ``function`` is the name of the ``gettext`` function used (if the
+      string was extracted from embedded Python code), and
+    *  ``message`` is the string itself (a ``unicode`` object, or a tuple
+       of ``unicode`` objects for functions with multiple string arguments).
+
+    This extraction function operates on the AST and is because of that unable
+    to extract any comments.  For comment support you have to use the babel
+    extraction interface or extract comments yourself.
+    """
+    for node in node.find_all(nodes.Call):
+        if not isinstance(node.node, nodes.Name) or \
+           node.node.name not in gettext_functions:
+            continue
+
+        strings = []
+        for arg in node.args:
+            if isinstance(arg, nodes.Const) and \
+               isinstance(arg.value, basestring):
+                strings.append(arg.value)
+            else:
+                strings.append(None)
+
+        for arg in node.kwargs:
+            strings.append(None)
+        if node.dyn_args is not None:
+            strings.append(None)
+        if node.dyn_kwargs is not None:
+            strings.append(None)
+
+        if not babel_style:
+            strings = tuple(x for x in strings if x is not None)
+            if not strings:
+                continue
+        else:
+            if len(strings) == 1:
+                strings = strings[0]
+            else:
+                strings = tuple(strings)
+        yield node.lineno, node.node.name, strings
+
+
+class _CommentFinder(object):
+    """Helper class to find comments in a token stream.  Can only
+    find comments for gettext calls forwards.  Once the comment
+    from line 4 is found, a comment for line 1 will not return a
+    usable value.
+    """
+
+    def __init__(self, tokens, comment_tags):
+        self.tokens = tokens
+        self.comment_tags = comment_tags
+        self.offset = 0
+        self.last_lineno = 0
+
+    def find_backwards(self, offset):
+        try:
+            for _, token_type, token_value in \
+                    reversed(self.tokens[self.offset:offset]):
+                if token_type in ('comment', 'linecomment'):
+                    try:
+                        prefix, comment = token_value.split(None, 1)
+                    except ValueError:
+                        continue
+                    if prefix in self.comment_tags:
+                        return [comment.rstrip()]
+            return []
+        finally:
+            self.offset = offset
+
+    def find_comments(self, lineno):
+        if not self.comment_tags or self.last_lineno > lineno:
+            return []
+        for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset:]):
+            if token_lineno > lineno:
+                return self.find_backwards(self.offset + idx)
+        return self.find_backwards(len(self.tokens))
+
+
+def babel_extract(fileobj, keywords, comment_tags, options):
+    """Babel extraction method for Jinja templates.
+
+    .. versionchanged:: 2.3
+       Basic support for translation comments was added.  If `comment_tags`
+       is now set to a list of keywords for extraction, the extractor will
+       try to find the best preceeding comment that begins with one of the
+       keywords.  For best results, make sure to not have more than one
+       gettext call in one line of code and the matching comment in the
+       same line or the line before.
+
+    .. versionchanged:: 2.5.1
+       The `newstyle_gettext` flag can be set to `True` to enable newstyle
+       gettext calls.
+
+    :param fileobj: the file-like object the messages should be extracted from
+    :param keywords: a list of keywords (i.e. function names) that should be
+                     recognized as translation functions
+    :param comment_tags: a list of translator tags to search for and include
+                         in the results.
+    :param options: a dictionary of additional options (optional)
+    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
+             (comments will be empty currently)
+    """
+    extensions = set()
+    for extension in options.get('extensions', '').split(','):
+        extension = extension.strip()
+        if not extension:
+            continue
+        extensions.add(import_string(extension))
+    if InternationalizationExtension not in extensions:
+        extensions.add(InternationalizationExtension)
+
+    def getbool(options, key, default=False):
+        options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true')
+
+    environment = Environment(
+        options.get('block_start_string', BLOCK_START_STRING),
+        options.get('block_end_string', BLOCK_END_STRING),
+        options.get('variable_start_string', VARIABLE_START_STRING),
+        options.get('variable_end_string', VARIABLE_END_STRING),
+        options.get('comment_start_string', COMMENT_START_STRING),
+        options.get('comment_end_string', COMMENT_END_STRING),
+        options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
+        options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
+        getbool(options, 'trim_blocks', TRIM_BLOCKS),
+        NEWLINE_SEQUENCE, frozenset(extensions),
+        cache_size=0,
+        auto_reload=False
+    )
+
+    if getbool(options, 'newstyle_gettext'):
+        environment.newstyle_gettext = True
+
+    source = fileobj.read().decode(options.get('encoding', 'utf-8'))
+    try:
+        node = environment.parse(source)
+        tokens = list(environment.lex(environment.preprocess(source)))
+    except TemplateSyntaxError, e:
+        # skip templates with syntax errors
+        return
+
+    finder = _CommentFinder(tokens, comment_tags)
+    for lineno, func, message in extract_from_ast(node, keywords):
+        yield lineno, func, message, finder.find_comments(lineno)
+
+
+#: nicer import names
+i18n = InternationalizationExtension
+do = ExprStmtExtension
+loopcontrols = LoopControlExtension
+with_ = WithExtension
+autoescape = AutoEscapeExtension


[08/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html
new file mode 100644
index 0000000..c4c6303
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html
new file mode 100644
index 0000000..a9c353e
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py b/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py
new file mode 100644
index 0000000..813dd56
--- /dev/null
+++ b/ambari-common/src/main/python/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 jinja2 import Environment, FileSystemLoader
+from 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/570de228/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim b/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim
new file mode 100644
index 0000000..3f9cba4
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim b/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim
new file mode 100644
index 0000000..919954b
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py b/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py
new file mode 100644
index 0000000..6d9e76c
--- /dev/null
+++ b/ambari-common/src/main/python/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 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 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/570de228/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py b/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py
new file mode 100644
index 0000000..2d4ab9a
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html b/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html
new file mode 100644
index 0000000..d0fbe38
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html b/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html
new file mode 100644
index 0000000..3f21a12
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/subtemplate.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/subtemplate.html b/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/subtemplate.html
new file mode 100644
index 0000000..980a0d5
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/subtemplate.html
@@ -0,0 +1 @@
+Hello World!

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/ext/djangojinja2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/djangojinja2.py b/ambari-common/src/main/python/jinja2/ext/djangojinja2.py
new file mode 100644
index 0000000..d24d164
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/ext/djangojinja2.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""
+    djangojinja2
+    ~~~~~~~~~~~~
+
+    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 jinja2 import Environment, FileSystemLoader, TemplateNotFound
+from 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/570de228/ambari-common/src/main/python/jinja2/ext/inlinegettext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/inlinegettext.py b/ambari-common/src/main/python/jinja2/ext/inlinegettext.py
new file mode 100644
index 0000000..cf4ed5e
--- /dev/null
+++ b/ambari-common/src/main/python/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 jinja2.ext import Extension
+from jinja2.lexer import Token, count_newlines
+from 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)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/ext/jinja.el
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/jinja.el b/ambari-common/src/main/python/jinja2/ext/jinja.el
new file mode 100644
index 0000000..401ba29
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/ext/jinja.el
@@ -0,0 +1,213 @@
+;;; jinja.el --- Jinja mode highlighting
+;;
+;; Author: Georg Brandl
+;; Copyright: (c) 2009 by the Jinja Team
+;; Last modified: 2008-05-22 23:04 by gbr
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Mostly ripped off django-mode by Lennart Borgman.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(defconst jinja-font-lock-keywords
+  (list
+;   (cons (rx "{% comment %}" (submatch (0+ anything))
+;             "{% endcomment %}") (list 1 font-lock-comment-face))
+   '("{# ?\\(.*?\\) ?#}" . (1 font-lock-comment-face))
+   '("{%-?\\|-?%}\\|{{\\|}}" . font-lock-preprocessor-face)
+   '("{#\\|#}" . font-lock-comment-delimiter-face)
+   ;; first word in a block is a command
+   '("{%-?[ \t\n]*\\([a-zA-Z_]+\\)" . (1 font-lock-keyword-face))
+   ;; variables
+   '("\\({{ ?\\)\\([^|]*?\\)\\(|.*?\\)? ?}}" . (1 font-lock-variable-name-face))
+   ;; keywords and builtins
+   (cons (rx word-start
+             (or "in" "as" "recursive" "not" "and" "or" "if" "else"
+                 "import" "with" "without" "context")
+             word-end)
+         font-lock-keyword-face)
+   (cons (rx word-start
+             (or "true" "false" "none" "loop" "self" "super")
+             word-end)
+         font-lock-builtin-face)
+   ;; tests
+   '("\\(is\\)[ \t]*\\(not\\)[ \t]*\\([a-zA-Z_]+\\)"
+     (1 font-lock-keyword-face) (2 font-lock-keyword-face)
+     (3 font-lock-function-name-face))
+   ;; builtin filters
+   (cons (rx
+          "|" (* space)
+          (submatch
+           (or "abs" "batch" "capitalize" "capture" "center" "count" "default"
+               "dformat" "dictsort" "e" "escape" "filesizeformat" "first"
+               "float" "format" "getattribute" "getitem" "groupby" "indent"
+               "int" "join" "jsonencode" "last" "length" "lower" "markdown"
+               "pprint" "random" "replace" "reverse" "round" "rst" "slice"
+               "sort" "string" "striptags" "sum" "textile" "title" "trim"
+               "truncate" "upper" "urlencode" "urlize" "wordcount" "wordwrap"
+               "xmlattr")))
+         (list 1 font-lock-builtin-face))
+   )
+   "Minimal highlighting expressions for Jinja mode")
+
+(define-derived-mode jinja-mode nil "Jinja"
+  "Simple Jinja mode for use with `mumamo-mode'.
+This mode only provides syntax highlighting."
+  ;;(set (make-local-variable 'comment-start) "{#")
+  ;;(set (make-local-variable 'comment-end)   "#}")
+  (setq font-lock-defaults '(jinja-font-lock-keywords)))
+
+;; mumamo stuff
+
+(when (require 'mumamo nil t)
+
+  (defun mumamo-chunk-jinja3(pos min max)
+    "Find {# ... #}.  Return range and `jinja-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX."
+    (mumamo-find-possible-chunk pos min max
+                                'mumamo-search-bw-exc-start-jinja3
+                                'mumamo-search-bw-exc-end-jinja3
+                                'mumamo-search-fw-exc-start-jinja3
+                                'mumamo-search-fw-exc-end-jinja3))
+
+  (defun mumamo-chunk-jinja2(pos min max)
+    "Find {{ ... }}.  Return range and `jinja-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX."
+    (mumamo-find-possible-chunk pos min max
+                                'mumamo-search-bw-exc-start-jinja2
+                                'mumamo-search-bw-exc-end-jinja2
+                                'mumamo-search-fw-exc-start-jinja2
+                                'mumamo-search-fw-exc-end-jinja2))
+
+  (defun mumamo-chunk-jinja (pos min max)
+    "Find {% ... %}.  Return range and `jinja-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX."
+    (mumamo-find-possible-chunk pos min max
+                                'mumamo-search-bw-exc-start-jinja
+                                'mumamo-search-bw-exc-end-jinja
+                                'mumamo-search-fw-exc-start-jinja
+                                'mumamo-search-fw-exc-end-jinja))
+
+  (defun mumamo-search-bw-exc-start-jinja (pos min)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MIN is where to stop."
+    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{%")))
+      (and exc-start
+           (<= exc-start pos)
+           (cons exc-start 'jinja-mode))))
+
+  (defun mumamo-search-bw-exc-start-jinja2(pos min)
+    "Helper for `mumamo-chunk-jinja2'.
+POS is where to start search and MIN is where to stop."
+    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{{")))
+      (and exc-start
+           (<= exc-start pos)
+           (cons exc-start 'jinja-mode))))
+
+  (defun mumamo-search-bw-exc-start-jinja3(pos min)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MIN is where to stop."
+    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{#")))
+      (and exc-start
+           (<= exc-start pos)
+           (cons exc-start 'jinja-mode))))
+
+  (defun mumamo-search-bw-exc-end-jinja (pos min)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MIN is where to stop."
+    (mumamo-chunk-end-bw-str-inc pos min "%}"))
+
+  (defun mumamo-search-bw-exc-end-jinja2(pos min)
+    "Helper for `mumamo-chunk-jinja2'.
+POS is where to start search and MIN is where to stop."
+    (mumamo-chunk-end-bw-str-inc pos min "}}"))
+
+  (defun mumamo-search-bw-exc-end-jinja3(pos min)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MIN is where to stop."
+    (mumamo-chunk-end-bw-str-inc pos min "#}"))
+
+  (defun mumamo-search-fw-exc-start-jinja (pos max)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-start-fw-str-inc pos max "{%"))
+
+  (defun mumamo-search-fw-exc-start-jinja2(pos max)
+    "Helper for `mumamo-chunk-jinja2'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-start-fw-str-inc pos max "{{"))
+
+  (defun mumamo-search-fw-exc-start-jinja3(pos max)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-start-fw-str-inc pos max "{#"))
+
+  (defun mumamo-search-fw-exc-end-jinja (pos max)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-end-fw-str-inc pos max "%}"))
+
+  (defun mumamo-search-fw-exc-end-jinja2(pos max)
+    "Helper for `mumamo-chunk-jinja2'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-end-fw-str-inc pos max "}}"))
+
+  (defun mumamo-search-fw-exc-end-jinja3(pos max)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-end-fw-str-inc pos max "#}"))
+
+;;;###autoload
+  (define-mumamo-multi-major-mode jinja-html-mumamo
+    "Turn on multiple major modes for Jinja with main mode `html-mode'.
+This also covers inlined style and javascript."
+    ("Jinja HTML Family" html-mode
+     (mumamo-chunk-jinja
+      mumamo-chunk-jinja2
+      mumamo-chunk-jinja3
+      mumamo-chunk-inlined-style
+      mumamo-chunk-inlined-script
+      mumamo-chunk-style=
+      mumamo-chunk-onjs=
+      )))
+
+;;;###autoload
+  (define-mumamo-multi-major-mode jinja-nxhtml-mumamo
+    "Turn on multiple major modes for Jinja with main mode `nxhtml-mode'.
+This also covers inlined style and javascript."
+    ("Jinja nXhtml Family" nxhtml-mode
+     (mumamo-chunk-jinja
+      mumamo-chunk-jinja2
+      mumamo-chunk-jinja3
+      mumamo-chunk-inlined-style
+      mumamo-chunk-inlined-script
+      mumamo-chunk-style=
+      mumamo-chunk-onjs=
+      )))
+  )
+
+(provide 'jinja)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; jinja.el ends here

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2-debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2-debug.py b/ambari-common/src/main/python/jinja2/jinja2-debug.py
new file mode 100644
index 0000000..c9c482f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2-debug.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    Jinja2 Debug Interface
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Helper script for internal Jinja2 debugging.  Requires Werkzeug.
+
+    :copyright: Copyright 2010 by Armin Ronacher.
+    :license: BSD.
+"""
+import sys
+import jinja2
+from werkzeug import script
+
+env = jinja2.Environment(extensions=['jinja2.ext.i18n', 'jinja2.ext.do',
+                                     'jinja2.ext.loopcontrols'])
+
+def shell_init_func():
+    def _compile(x):
+        print env.compile(x, raw=True)
+    result = {
+        'e':        env,
+        'c':        _compile,
+        't':        env.from_string,
+        'p':        env.parse
+    }
+    for key in jinja2.__all__:
+        result[key] = getattr(jinja2, key)
+    return result
+
+
+def action_compile():
+    print env.compile(sys.stdin.read(), raw=True)
+
+action_shell = script.make_shell(shell_init_func)
+
+
+if __name__ == '__main__':
+    script.run()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/__init__.py
new file mode 100644
index 0000000..f944e11
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/__init__.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2
+    ~~~~~~
+
+    Jinja2 is a template engine written in pure Python.  It provides a
+    Django inspired non-XML syntax but supports inline expressions and
+    an optional sandboxed environment.
+
+    Nutshell
+    --------
+
+    Here a small example of a Jinja2 template::
+
+        {% extends 'base.html' %}
+        {% block title %}Memberlist{% endblock %}
+        {% block content %}
+          <ul>
+          {% for user in users %}
+            <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+          {% endfor %}
+          </ul>
+        {% endblock %}
+
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+__docformat__ = 'restructuredtext en'
+try:
+    __version__ = __import__('pkg_resources') \
+        .get_distribution('Jinja2').version
+except:
+    __version__ = 'unknown'
+
+# high level interface
+from jinja2.environment import Environment, Template
+
+# loaders
+from jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \
+     DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \
+     ModuleLoader
+
+# bytecode caches
+from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
+     MemcachedBytecodeCache
+
+# undefined types
+from jinja2.runtime import Undefined, DebugUndefined, StrictUndefined
+
+# exceptions
+from jinja2.exceptions import TemplateError, UndefinedError, \
+     TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \
+     TemplateAssertionError
+
+# decorators and public utilities
+from jinja2.filters import environmentfilter, contextfilter, \
+     evalcontextfilter
+from jinja2.utils import Markup, escape, clear_caches, \
+     environmentfunction, evalcontextfunction, contextfunction, \
+     is_undefined
+
+__all__ = [
+    'Environment', 'Template', 'BaseLoader', 'FileSystemLoader',
+    'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader',
+    'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache',
+    'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined',
+    'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound',
+    'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError',
+    'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape',
+    'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined',
+    'evalcontextfilter', 'evalcontextfunction'
+]

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c b/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c
new file mode 100644
index 0000000..e756d8e
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c
@@ -0,0 +1,78 @@
+/**
+ * jinja2._debugsupport
+ * ~~~~~~~~~~~~~~~~~~~~
+ *
+ * C implementation of `tb_set_next`.
+ *
+ * :copyright: (c) 2010 by the Jinja Team.
+ * :license: BSD.
+ */
+
+#include <Python.h>
+
+
+static PyObject*
+tb_set_next(PyObject *self, PyObject *args)
+{
+	PyTracebackObject *tb, *old;
+	PyObject *next;
+
+	if (!PyArg_ParseTuple(args, "O!O:tb_set_next", &PyTraceBack_Type, &tb, &next))
+		return NULL;
+	if (next == Py_None)
+		next = NULL;
+	else if (!PyTraceBack_Check(next)) {
+		PyErr_SetString(PyExc_TypeError,
+				"tb_set_next arg 2 must be traceback or None");
+		return NULL;
+	}
+	else
+		Py_INCREF(next);
+
+	old = tb->tb_next;
+	tb->tb_next = (PyTracebackObject*)next;
+	Py_XDECREF(old);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMethodDef module_methods[] = {
+	{"tb_set_next", (PyCFunction)tb_set_next, METH_VARARGS,
+	 "Set the tb_next member of a traceback object."},
+	{NULL, NULL, 0, NULL}		/* Sentinel */
+};
+
+
+#if PY_MAJOR_VERSION < 3
+
+#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+init_debugsupport(void)
+{
+	Py_InitModule3("jinja2._debugsupport", module_methods, "");
+}
+
+#else /* Python 3.x module initialization */
+
+static struct PyModuleDef module_definition = {
+        PyModuleDef_HEAD_INIT,
+	"jinja2._debugsupport",
+	NULL,
+	-1,
+	module_methods,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+PyMODINIT_FUNC
+PyInit__debugsupport(void)
+{
+	return PyModule_Create(&module_definition);
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py
new file mode 100644
index 0000000..ec7bd57
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py
@@ -0,0 +1,225 @@
+# -*- coding: utf-8 -*-
+"""
+    markupsafe
+    ~~~~~~~~~~
+
+    Implements a Markup string.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+from itertools import imap
+
+
+__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
+
+
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^;]+);')
+
+
+class Markup(unicode):
+    r"""Marks a string as being safe for inclusion in HTML/XML output without
+    needing to be escaped.  This implements the `__html__` interface a couple
+    of frameworks and web applications use.  :class:`Markup` is a direct
+    subclass of `unicode` and provides all the methods of `unicode` just that
+    it escapes arguments passed and always returns `Markup`.
+
+    The `escape` function returns markup objects so that double escaping can't
+    happen.
+
+    The constructor of the :class:`Markup` class can be used for three
+    different things:  When passed an unicode object it's assumed to be safe,
+    when passed an object with an HTML representation (has an `__html__`
+    method) that representation is used, otherwise the object passed is
+    converted into a unicode string and then assumed to be safe:
+
+    >>> Markup("Hello <em>World</em>!")
+    Markup(u'Hello <em>World</em>!')
+    >>> class Foo(object):
+    ...  def __html__(self):
+    ...   return '<a href="#">foo</a>'
+    ... 
+    >>> Markup(Foo())
+    Markup(u'<a href="#">foo</a>')
+
+    If you want object passed being always treated as unsafe you can use the
+    :meth:`escape` classmethod to create a :class:`Markup` object:
+
+    >>> Markup.escape("Hello <em>World</em>!")
+    Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
+
+    Operations on a markup string are markup aware which means that all
+    arguments are passed through the :func:`escape` function:
+
+    >>> em = Markup("<em>%s</em>")
+    >>> em % "foo & bar"
+    Markup(u'<em>foo &amp; bar</em>')
+    >>> strong = Markup("<strong>%(text)s</strong>")
+    >>> strong % {'text': '<blink>hacker here</blink>'}
+    Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
+    >>> Markup("<em>Hello</em> ") + "<foo>"
+    Markup(u'<em>Hello</em> &lt;foo&gt;')
+    """
+    __slots__ = ()
+
+    def __new__(cls, base=u'', encoding=None, errors='strict'):
+        if hasattr(base, '__html__'):
+            base = base.__html__()
+        if encoding is None:
+            return unicode.__new__(cls, base)
+        return unicode.__new__(cls, base, encoding, errors)
+
+    def __html__(self):
+        return self
+
+    def __add__(self, other):
+        if hasattr(other, '__html__') or isinstance(other, basestring):
+            return self.__class__(unicode(self) + unicode(escape(other)))
+        return NotImplemented
+
+    def __radd__(self, other):
+        if hasattr(other, '__html__') or isinstance(other, basestring):
+            return self.__class__(unicode(escape(other)) + unicode(self))
+        return NotImplemented
+
+    def __mul__(self, num):
+        if isinstance(num, (int, long)):
+            return self.__class__(unicode.__mul__(self, num))
+        return NotImplemented
+    __rmul__ = __mul__
+
+    def __mod__(self, arg):
+        if isinstance(arg, tuple):
+            arg = tuple(imap(_MarkupEscapeHelper, arg))
+        else:
+            arg = _MarkupEscapeHelper(arg)
+        return self.__class__(unicode.__mod__(self, arg))
+
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            unicode.__repr__(self)
+        )
+
+    def join(self, seq):
+        return self.__class__(unicode.join(self, imap(escape, seq)))
+    join.__doc__ = unicode.join.__doc__
+
+    def split(self, *args, **kwargs):
+        return map(self.__class__, unicode.split(self, *args, **kwargs))
+    split.__doc__ = unicode.split.__doc__
+
+    def rsplit(self, *args, **kwargs):
+        return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
+    rsplit.__doc__ = unicode.rsplit.__doc__
+
+    def splitlines(self, *args, **kwargs):
+        return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
+    splitlines.__doc__ = unicode.splitlines.__doc__
+
+    def unescape(self):
+        r"""Unescape markup again into an unicode string.  This also resolves
+        known HTML4 and XHTML entities:
+
+        >>> Markup("Main &raquo; <em>About</em>").unescape()
+        u'Main \xbb <em>About</em>'
+        """
+        from jinja2._markupsafe._constants import HTML_ENTITIES
+        def handle_match(m):
+            name = m.group(1)
+            if name in HTML_ENTITIES:
+                return unichr(HTML_ENTITIES[name])
+            try:
+                if name[:2] in ('#x', '#X'):
+                    return unichr(int(name[2:], 16))
+                elif name.startswith('#'):
+                    return unichr(int(name[1:]))
+            except ValueError:
+                pass
+            return u''
+        return _entity_re.sub(handle_match, unicode(self))
+
+    def striptags(self):
+        r"""Unescape markup into an unicode string and strip all tags.  This
+        also resolves known HTML4 and XHTML entities.  Whitespace is
+        normalized to one:
+
+        >>> Markup("Main &raquo;  <em>About</em>").striptags()
+        u'Main \xbb About'
+        """
+        stripped = u' '.join(_striptags_re.sub('', self).split())
+        return Markup(stripped).unescape()
+
+    @classmethod
+    def escape(cls, s):
+        """Escape the string.  Works like :func:`escape` with the difference
+        that for subclasses of :class:`Markup` this function would return the
+        correct subclass.
+        """
+        rv = escape(s)
+        if rv.__class__ is not cls:
+            return cls(rv)
+        return rv
+
+    def make_wrapper(name):
+        orig = getattr(unicode, name)
+        def func(self, *args, **kwargs):
+            args = _escape_argspec(list(args), enumerate(args))
+            _escape_argspec(kwargs, kwargs.iteritems())
+            return self.__class__(orig(self, *args, **kwargs))
+        func.__name__ = orig.__name__
+        func.__doc__ = orig.__doc__
+        return func
+
+    for method in '__getitem__', 'capitalize', \
+                  'title', 'lower', 'upper', 'replace', 'ljust', \
+                  'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
+                  'translate', 'expandtabs', 'swapcase', 'zfill':
+        locals()[method] = make_wrapper(method)
+
+    # new in python 2.5
+    if hasattr(unicode, 'partition'):
+        partition = make_wrapper('partition'),
+        rpartition = make_wrapper('rpartition')
+
+    # new in python 2.6
+    if hasattr(unicode, 'format'):
+        format = make_wrapper('format')
+
+    # not in python 3
+    if hasattr(unicode, '__getslice__'):
+        __getslice__ = make_wrapper('__getslice__')
+
+    del method, make_wrapper
+
+
+def _escape_argspec(obj, iterable):
+    """Helper for various string-wrapped functions."""
+    for key, value in iterable:
+        if hasattr(value, '__html__') or isinstance(value, basestring):
+            obj[key] = escape(value)
+    return obj
+
+
+class _MarkupEscapeHelper(object):
+    """Helper for Markup.__mod__"""
+
+    def __init__(self, obj):
+        self.obj = obj
+
+    __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
+    __str__ = lambda s: str(escape(s.obj))
+    __unicode__ = lambda s: unicode(escape(s.obj))
+    __repr__ = lambda s: str(escape(repr(s.obj)))
+    __int__ = lambda s: int(s.obj)
+    __float__ = lambda s: float(s.obj)
+
+
+# we have to import it down here as the speedups and native
+# modules imports the markup type which is define above.
+try:
+    from jinja2._markupsafe._speedups import escape, escape_silent, soft_unicode
+except ImportError:
+    from jinja2._markupsafe._native import escape, escape_silent, soft_unicode

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py
new file mode 100644
index 0000000..e694faf
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2._markupsafe._bundle
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    This script pulls in markupsafe from a source folder and
+    bundles it with Jinja2.  It does not pull in the speedups
+    module though.
+
+    :copyright: Copyright 2010 by the Jinja team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+import sys
+import os
+import re
+
+
+def rewrite_imports(lines):
+    for idx, line in enumerate(lines):
+        new_line = re.sub(r'(import|from)\s+markupsafe\b',
+                          r'\1 jinja2._markupsafe', line)
+        if new_line != line:
+            lines[idx] = new_line
+
+
+def main():
+    if len(sys.argv) != 2:
+        print 'error: only argument is path to markupsafe'
+        sys.exit(1)
+    basedir = os.path.dirname(__file__)
+    markupdir = sys.argv[1]
+    for filename in os.listdir(markupdir):
+        if filename.endswith('.py'):
+            f = open(os.path.join(markupdir, filename))
+            try:
+                lines = list(f)
+            finally:
+                f.close()
+            rewrite_imports(lines)
+            f = open(os.path.join(basedir, filename), 'w')
+            try:
+                for line in lines:
+                    f.write(line)
+            finally:
+                f.close()
+
+
+if __name__ == '__main__':
+    main()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py
new file mode 100644
index 0000000..919bf03
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+"""
+    markupsafe._constants
+    ~~~~~~~~~~~~~~~~~~~~~
+
+    Highlevel implementation of the Markup string.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+
+
+HTML_ENTITIES = {
+    'AElig': 198,
+    'Aacute': 193,
+    'Acirc': 194,
+    'Agrave': 192,
+    'Alpha': 913,
+    'Aring': 197,
+    'Atilde': 195,
+    'Auml': 196,
+    'Beta': 914,
+    'Ccedil': 199,
+    'Chi': 935,
+    'Dagger': 8225,
+    'Delta': 916,
+    'ETH': 208,
+    'Eacute': 201,
+    'Ecirc': 202,
+    'Egrave': 200,
+    'Epsilon': 917,
+    'Eta': 919,
+    'Euml': 203,
+    'Gamma': 915,
+    'Iacute': 205,
+    'Icirc': 206,
+    'Igrave': 204,
+    'Iota': 921,
+    'Iuml': 207,
+    'Kappa': 922,
+    'Lambda': 923,
+    'Mu': 924,
+    'Ntilde': 209,
+    'Nu': 925,
+    'OElig': 338,
+    'Oacute': 211,
+    'Ocirc': 212,
+    'Ograve': 210,
+    'Omega': 937,
+    'Omicron': 927,
+    'Oslash': 216,
+    'Otilde': 213,
+    'Ouml': 214,
+    'Phi': 934,
+    'Pi': 928,
+    'Prime': 8243,
+    'Psi': 936,
+    'Rho': 929,
+    'Scaron': 352,
+    'Sigma': 931,
+    'THORN': 222,
+    'Tau': 932,
+    'Theta': 920,
+    'Uacute': 218,
+    'Ucirc': 219,
+    'Ugrave': 217,
+    'Upsilon': 933,
+    'Uuml': 220,
+    'Xi': 926,
+    'Yacute': 221,
+    'Yuml': 376,
+    'Zeta': 918,
+    'aacute': 225,
+    'acirc': 226,
+    'acute': 180,
+    'aelig': 230,
+    'agrave': 224,
+    'alefsym': 8501,
+    'alpha': 945,
+    'amp': 38,
+    'and': 8743,
+    'ang': 8736,
+    'apos': 39,
+    'aring': 229,
+    'asymp': 8776,
+    'atilde': 227,
+    'auml': 228,
+    'bdquo': 8222,
+    'beta': 946,
+    'brvbar': 166,
+    'bull': 8226,
+    'cap': 8745,
+    'ccedil': 231,
+    'cedil': 184,
+    'cent': 162,
+    'chi': 967,
+    'circ': 710,
+    'clubs': 9827,
+    'cong': 8773,
+    'copy': 169,
+    'crarr': 8629,
+    'cup': 8746,
+    'curren': 164,
+    'dArr': 8659,
+    'dagger': 8224,
+    'darr': 8595,
+    'deg': 176,
+    'delta': 948,
+    'diams': 9830,
+    'divide': 247,
+    'eacute': 233,
+    'ecirc': 234,
+    'egrave': 232,
+    'empty': 8709,
+    'emsp': 8195,
+    'ensp': 8194,
+    'epsilon': 949,
+    'equiv': 8801,
+    'eta': 951,
+    'eth': 240,
+    'euml': 235,
+    'euro': 8364,
+    'exist': 8707,
+    'fnof': 402,
+    'forall': 8704,
+    'frac12': 189,
+    'frac14': 188,
+    'frac34': 190,
+    'frasl': 8260,
+    'gamma': 947,
+    'ge': 8805,
+    'gt': 62,
+    'hArr': 8660,
+    'harr': 8596,
+    'hearts': 9829,
+    'hellip': 8230,
+    'iacute': 237,
+    'icirc': 238,
+    'iexcl': 161,
+    'igrave': 236,
+    'image': 8465,
+    'infin': 8734,
+    'int': 8747,
+    'iota': 953,
+    'iquest': 191,
+    'isin': 8712,
+    'iuml': 239,
+    'kappa': 954,
+    'lArr': 8656,
+    'lambda': 955,
+    'lang': 9001,
+    'laquo': 171,
+    'larr': 8592,
+    'lceil': 8968,
+    'ldquo': 8220,
+    'le': 8804,
+    'lfloor': 8970,
+    'lowast': 8727,
+    'loz': 9674,
+    'lrm': 8206,
+    'lsaquo': 8249,
+    'lsquo': 8216,
+    'lt': 60,
+    'macr': 175,
+    'mdash': 8212,
+    'micro': 181,
+    'middot': 183,
+    'minus': 8722,
+    'mu': 956,
+    'nabla': 8711,
+    'nbsp': 160,
+    'ndash': 8211,
+    'ne': 8800,
+    'ni': 8715,
+    'not': 172,
+    'notin': 8713,
+    'nsub': 8836,
+    'ntilde': 241,
+    'nu': 957,
+    'oacute': 243,
+    'ocirc': 244,
+    'oelig': 339,
+    'ograve': 242,
+    'oline': 8254,
+    'omega': 969,
+    'omicron': 959,
+    'oplus': 8853,
+    'or': 8744,
+    'ordf': 170,
+    'ordm': 186,
+    'oslash': 248,
+    'otilde': 245,
+    'otimes': 8855,
+    'ouml': 246,
+    'para': 182,
+    'part': 8706,
+    'permil': 8240,
+    'perp': 8869,
+    'phi': 966,
+    'pi': 960,
+    'piv': 982,
+    'plusmn': 177,
+    'pound': 163,
+    'prime': 8242,
+    'prod': 8719,
+    'prop': 8733,
+    'psi': 968,
+    'quot': 34,
+    'rArr': 8658,
+    'radic': 8730,
+    'rang': 9002,
+    'raquo': 187,
+    'rarr': 8594,
+    'rceil': 8969,
+    'rdquo': 8221,
+    'real': 8476,
+    'reg': 174,
+    'rfloor': 8971,
+    'rho': 961,
+    'rlm': 8207,
+    'rsaquo': 8250,
+    'rsquo': 8217,
+    'sbquo': 8218,
+    'scaron': 353,
+    'sdot': 8901,
+    'sect': 167,
+    'shy': 173,
+    'sigma': 963,
+    'sigmaf': 962,
+    'sim': 8764,
+    'spades': 9824,
+    'sub': 8834,
+    'sube': 8838,
+    'sum': 8721,
+    'sup': 8835,
+    'sup1': 185,
+    'sup2': 178,
+    'sup3': 179,
+    'supe': 8839,
+    'szlig': 223,
+    'tau': 964,
+    'there4': 8756,
+    'theta': 952,
+    'thetasym': 977,
+    'thinsp': 8201,
+    'thorn': 254,
+    'tilde': 732,
+    'times': 215,
+    'trade': 8482,
+    'uArr': 8657,
+    'uacute': 250,
+    'uarr': 8593,
+    'ucirc': 251,
+    'ugrave': 249,
+    'uml': 168,
+    'upsih': 978,
+    'upsilon': 965,
+    'uuml': 252,
+    'weierp': 8472,
+    'xi': 958,
+    'yacute': 253,
+    'yen': 165,
+    'yuml': 255,
+    'zeta': 950,
+    'zwj': 8205,
+    'zwnj': 8204
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py
new file mode 100644
index 0000000..7b95828
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+"""
+    markupsafe._native
+    ~~~~~~~~~~~~~~~~~~
+
+    Native Python implementation the C module is not compiled.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+from jinja2._markupsafe import Markup
+
+
+def escape(s):
+    """Convert the characters &, <, >, ' and " in string s to HTML-safe
+    sequences.  Use this if you need to display text that might contain
+    such characters in HTML.  Marks return value as markup string.
+    """
+    if hasattr(s, '__html__'):
+        return s.__html__()
+    return Markup(unicode(s)
+        .replace('&', '&amp;')
+        .replace('>', '&gt;')
+        .replace('<', '&lt;')
+        .replace("'", '&#39;')
+        .replace('"', '&#34;')
+    )
+
+
+def escape_silent(s):
+    """Like :func:`escape` but converts `None` into an empty
+    markup string.
+    """
+    if s is None:
+        return Markup()
+    return escape(s)
+
+
+def soft_unicode(s):
+    """Make a string unicode if it isn't already.  That way a markup
+    string is not converted back to unicode.
+    """
+    if not isinstance(s, unicode):
+        s = unicode(s)
+    return s

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py
new file mode 100644
index 0000000..c1ce394
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py
@@ -0,0 +1,80 @@
+import gc
+import unittest
+from jinja2._markupsafe import Markup, escape, escape_silent
+
+
+class MarkupTestCase(unittest.TestCase):
+
+    def test_markup_operations(self):
+        # adding two strings should escape the unsafe one
+        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+        safe = Markup('<em>username</em>')
+        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
+
+        # string interpolations are safe to use too
+        assert Markup('<em>%s</em>') % '<bad user>' == \
+               '<em>&lt;bad user&gt;</em>'
+        assert Markup('<em>%(username)s</em>') % {
+            'username': '<bad user>'
+        } == '<em>&lt;bad user&gt;</em>'
+
+        # an escaped object is markup too
+        assert type(Markup('foo') + 'bar') is Markup
+
+        # and it implements __html__ by returning itself
+        x = Markup("foo")
+        assert x.__html__() is x
+
+        # it also knows how to treat __html__ objects
+        class Foo(object):
+            def __html__(self):
+                return '<em>awesome</em>'
+            def __unicode__(self):
+                return 'awesome'
+        assert Markup(Foo()) == '<em>awesome</em>'
+        assert Markup('<strong>%s</strong>') % Foo() == \
+               '<strong><em>awesome</em></strong>'
+
+        # escaping and unescaping
+        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+        assert Markup("&lt;test&gt;").unescape() == "<test>"
+
+    def test_all_set(self):
+        import jinja2._markupsafe as markup
+        for item in markup.__all__:
+            getattr(markup, item)
+
+    def test_escape_silent(self):
+        assert escape_silent(None) == Markup()
+        assert escape(None) == Markup(None)
+        assert escape_silent('<foo>') == Markup(u'&lt;foo&gt;')
+
+
+class MarkupLeakTestCase(unittest.TestCase):
+
+    def test_markup_leaks(self):
+        counts = set()
+        for count in xrange(20):
+            for item in xrange(1000):
+                escape("foo")
+                escape("<foo>")
+                escape(u"foo")
+                escape(u"<foo>")
+            counts.add(len(gc.get_objects()))
+        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(MarkupTestCase))
+
+    # this test only tests the c extension
+    if not hasattr(escape, 'func_code'):
+        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
+
+    return suite
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='suite')


[40/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el b/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el
new file mode 100644
index 0000000..da4800a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el
@@ -0,0 +1,213 @@
+;;; jinja.el --- Jinja mode highlighting
+;;
+;; Author: Georg Brandl
+;; Copyright: (c) 2009 by the Jinja Team
+;; Last modified: 2008-05-22 23:04 by gbr
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Mostly ripped off django-mode by Lennart Borgman.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(defconst jinja-font-lock-keywords
+  (list
+;   (cons (rx "{% comment %}" (submatch (0+ anything))
+;             "{% endcomment %}") (list 1 font-lock-comment-face))
+   '("{# ?\\(.*?\\) ?#}" . (1 font-lock-comment-face))
+   '("{%-?\\|-?%}\\|{{\\|}}" . font-lock-preprocessor-face)
+   '("{#\\|#}" . font-lock-comment-delimiter-face)
+   ;; first word in a block is a command
+   '("{%-?[ \t\n]*\\([a-zA-Z_]+\\)" . (1 font-lock-keyword-face))
+   ;; variables
+   '("\\({{ ?\\)\\([^|]*?\\)\\(|.*?\\)? ?}}" . (1 font-lock-variable-name-face))
+   ;; keywords and builtins
+   (cons (rx word-start
+             (or "in" "as" "recursive" "not" "and" "or" "if" "else"
+                 "import" "with" "without" "context")
+             word-end)
+         font-lock-keyword-face)
+   (cons (rx word-start
+             (or "true" "false" "none" "loop" "self" "super")
+             word-end)
+         font-lock-builtin-face)
+   ;; tests
+   '("\\(is\\)[ \t]*\\(not\\)[ \t]*\\([a-zA-Z_]+\\)"
+     (1 font-lock-keyword-face) (2 font-lock-keyword-face)
+     (3 font-lock-function-name-face))
+   ;; builtin filters
+   (cons (rx
+          "|" (* space)
+          (submatch
+           (or "abs" "batch" "capitalize" "capture" "center" "count" "default"
+               "dformat" "dictsort" "e" "escape" "filesizeformat" "first"
+               "float" "format" "getattribute" "getitem" "groupby" "indent"
+               "int" "join" "jsonencode" "last" "length" "lower" "markdown"
+               "pprint" "random" "replace" "reverse" "round" "rst" "slice"
+               "sort" "string" "striptags" "sum" "textile" "title" "trim"
+               "truncate" "upper" "urlencode" "urlize" "wordcount" "wordwrap"
+               "xmlattr")))
+         (list 1 font-lock-builtin-face))
+   )
+   "Minimal highlighting expressions for Jinja mode")
+
+(define-derived-mode jinja-mode nil "Jinja"
+  "Simple Jinja mode for use with `mumamo-mode'.
+This mode only provides syntax highlighting."
+  ;;(set (make-local-variable 'comment-start) "{#")
+  ;;(set (make-local-variable 'comment-end)   "#}")
+  (setq font-lock-defaults '(jinja-font-lock-keywords)))
+
+;; mumamo stuff
+
+(when (require 'mumamo nil t)
+
+  (defun mumamo-chunk-jinja3(pos min max)
+    "Find {# ... #}.  Return range and `jinja-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX."
+    (mumamo-find-possible-chunk pos min max
+                                'mumamo-search-bw-exc-start-jinja3
+                                'mumamo-search-bw-exc-end-jinja3
+                                'mumamo-search-fw-exc-start-jinja3
+                                'mumamo-search-fw-exc-end-jinja3))
+
+  (defun mumamo-chunk-ambari_jinja2(pos min max)
+    "Find {{ ... }}.  Return range and `jinja-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX."
+    (mumamo-find-possible-chunk pos min max
+                                'mumamo-search-bw-exc-start-ambari_jinja2
+                                'mumamo-search-bw-exc-end-ambari_jinja2
+                                'mumamo-search-fw-exc-start-ambari_jinja2
+                                'mumamo-search-fw-exc-end-ambari_jinja2))
+
+  (defun mumamo-chunk-jinja (pos min max)
+    "Find {% ... %}.  Return range and `jinja-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX."
+    (mumamo-find-possible-chunk pos min max
+                                'mumamo-search-bw-exc-start-jinja
+                                'mumamo-search-bw-exc-end-jinja
+                                'mumamo-search-fw-exc-start-jinja
+                                'mumamo-search-fw-exc-end-jinja))
+
+  (defun mumamo-search-bw-exc-start-jinja (pos min)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MIN is where to stop."
+    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{%")))
+      (and exc-start
+           (<= exc-start pos)
+           (cons exc-start 'jinja-mode))))
+
+  (defun mumamo-search-bw-exc-start-ambari_jinja2(pos min)
+    "Helper for `mumamo-chunk-ambari_jinja2'.
+POS is where to start search and MIN is where to stop."
+    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{{")))
+      (and exc-start
+           (<= exc-start pos)
+           (cons exc-start 'jinja-mode))))
+
+  (defun mumamo-search-bw-exc-start-jinja3(pos min)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MIN is where to stop."
+    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{#")))
+      (and exc-start
+           (<= exc-start pos)
+           (cons exc-start 'jinja-mode))))
+
+  (defun mumamo-search-bw-exc-end-jinja (pos min)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MIN is where to stop."
+    (mumamo-chunk-end-bw-str-inc pos min "%}"))
+
+  (defun mumamo-search-bw-exc-end-ambari_jinja2(pos min)
+    "Helper for `mumamo-chunk-ambari_jinja2'.
+POS is where to start search and MIN is where to stop."
+    (mumamo-chunk-end-bw-str-inc pos min "}}"))
+
+  (defun mumamo-search-bw-exc-end-jinja3(pos min)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MIN is where to stop."
+    (mumamo-chunk-end-bw-str-inc pos min "#}"))
+
+  (defun mumamo-search-fw-exc-start-jinja (pos max)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-start-fw-str-inc pos max "{%"))
+
+  (defun mumamo-search-fw-exc-start-ambari_jinja2(pos max)
+    "Helper for `mumamo-chunk-ambari_jinja2'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-start-fw-str-inc pos max "{{"))
+
+  (defun mumamo-search-fw-exc-start-jinja3(pos max)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-start-fw-str-inc pos max "{#"))
+
+  (defun mumamo-search-fw-exc-end-jinja (pos max)
+    "Helper for `mumamo-chunk-jinja'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-end-fw-str-inc pos max "%}"))
+
+  (defun mumamo-search-fw-exc-end-ambari_jinja2(pos max)
+    "Helper for `mumamo-chunk-ambari_jinja2'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-end-fw-str-inc pos max "}}"))
+
+  (defun mumamo-search-fw-exc-end-jinja3(pos max)
+    "Helper for `mumamo-chunk-jinja3'.
+POS is where to start search and MAX is where to stop."
+    (mumamo-chunk-end-fw-str-inc pos max "#}"))
+
+;;;###autoload
+  (define-mumamo-multi-major-mode jinja-html-mumamo
+    "Turn on multiple major modes for Jinja with main mode `html-mode'.
+This also covers inlined style and javascript."
+    ("Jinja HTML Family" html-mode
+     (mumamo-chunk-jinja
+      mumamo-chunk-ambari_jinja2
+      mumamo-chunk-jinja3
+      mumamo-chunk-inlined-style
+      mumamo-chunk-inlined-script
+      mumamo-chunk-style=
+      mumamo-chunk-onjs=
+      )))
+
+;;;###autoload
+  (define-mumamo-multi-major-mode jinja-nxhtml-mumamo
+    "Turn on multiple major modes for Jinja with main mode `nxhtml-mode'.
+This also covers inlined style and javascript."
+    ("Jinja nXhtml Family" nxhtml-mode
+     (mumamo-chunk-jinja
+      mumamo-chunk-ambari_jinja2
+      mumamo-chunk-jinja3
+      mumamo-chunk-inlined-style
+      mumamo-chunk-inlined-script
+      mumamo-chunk-style=
+      mumamo-chunk-onjs=
+      )))
+  )
+
+(provide 'jinja)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; jinja.el ends here

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py b/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py
new file mode 100644
index 0000000..f8d5571
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    Jinja2 Debug Interface
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Helper script for internal Jinja2 debugging.  Requires Werkzeug.
+
+    :copyright: Copyright 2010 by Armin Ronacher.
+    :license: BSD.
+"""
+import sys
+import ambari_jinja2
+from werkzeug import script
+
+env = ambari_jinja2.Environment(extensions=['ambari_jinja2.ext.i18n', 'ambari_jinja2.ext.do',
+                                     'ambari_jinja2.ext.loopcontrols'])
+
+def shell_init_func():
+    def _compile(x):
+        print env.compile(x, raw=True)
+    result = {
+        'e':        env,
+        'c':        _compile,
+        't':        env.from_string,
+        'p':        env.parse
+    }
+    for key in ambari_jinja2.__all__:
+        result[key] = getattr(ambari_jinja2, key)
+    return result
+
+
+def action_compile():
+    print env.compile(sys.stdin.read(), raw=True)
+
+action_shell = script.make_shell(shell_init_func)
+
+
+if __name__ == '__main__':
+    script.run()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc b/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc
new file mode 100644
index 0000000..4f85b49
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc
@@ -0,0 +1,301 @@
+# lint Python modules using external checkers.
+# 
+# This is the main checker controling the other ones and the reports
+# generation. It is itself both a raw checker and an astng checker in order
+# to:
+# * handle message activation / deactivation at the module level
+# * handle some basic but necessary stats'data (number of classes, methods...)
+# 
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Profiled execution.
+profile=no
+
+# Add <file or directory> to the black list. It should be a base name, not a
+# path. You may set this option multiple times.
+ignore=.svn
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Set the cache size for astng objects.
+cache-size=500
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable only checker(s) with the given id(s). This option conflict with the
+# disable-checker option
+#enable-checker=
+
+# Enable all checker(s) except those with the given id(s). This option conflict
+# with the disable-checker option
+#disable-checker=
+
+# Enable all messages in the listed categories.
+#enable-msg-cat=
+
+# Disable all messages in the listed categories.
+#disable-msg-cat=
+
+# Enable the message(s) with the given id(s).
+#enable-msg=
+
+# Disable the message(s) with the given id(s).
+disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201
+
+
+[REPORTS]
+
+# set the output format. Available formats are text, parseable, colorized and
+# html
+output-format=colorized
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells wether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note).You have access to the variables errors warning, statement which
+# respectivly contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (R0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (R0004).
+comment=no
+
+# Enable the report(s) with the given id(s).
+#enable-report=
+
+# Disable the report(s) with the given id(s).
+#disable-report=
+
+
+# checks for
+# * unused variables / imports
+# * undefined variables
+# * redefinition of variable from builtins or from an outer scope
+# * use of variable before assigment
+# 
+[VARIABLES]
+
+# Tells wether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching names used for dummy variables (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+# try to find bugs in the code using type inference
+# 
+[TYPECHECK]
+
+# Tells wether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# When zope mode is activated, consider the acquired-members option to ignore
+# access to some undefined attributes.
+zope=no
+
+# List of members which are usually get through zope's acquisition mecanism and
+# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
+acquired-members=REQUEST,acl_users,aq_parent
+
+
+# checks for :
+# * doc strings
+# * modules / classes / functions / methods / arguments / variables name
+# * number of arguments, local variables, branchs, returns and statements in
+# functions, methods
+# * required module attributes
+# * dangerous default values as arguments
+# * redefinition of function / method / class
+# * uses of the global statement
+# 
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=apply,input
+
+
+# checks for sign of poor/misdesign:
+# * number of methods, attributes, local variables...
+# * size, complexity of functions, methods
+# 
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=12
+
+# Maximum number of locals for function / method body
+max-locals=30
+
+# Maximum number of return / yield for function / method body
+max-returns=12
+
+# Maximum number of branch for function / method body
+max-branchs=30
+
+# Maximum number of statements in function / method body
+max-statements=60
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=20
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+# checks for
+# * external modules dependencies
+# * relative / wildcard imports
+# * cyclic imports
+# * uses of deprecated modules
+# 
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report R0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report R0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report R0402 must
+# not be disabled)
+int-import-graph=
+
+
+# checks for :
+# * methods without self as first argument
+# * overridden methods signature
+# * access only to existant members via self
+# * attributes not defined in the __init__ method
+# * supported interfaces implementation
+# * unreachable code
+# 
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+
+# checks for similarities and duplicated code. This computation may be
+# memory / CPU intensive, so you should disable it if you experiments some
+# problems.
+# 
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=10
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+# checks for:
+# * warning notes in the code like FIXME, XXX
+# * PEP 263: source code with non ascii character but no encoding declaration
+# 
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+# checks for :
+# * unauthorized constructions
+# * strict indentation
+# * line length
+# * use of <> instead of !=
+# 
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=90
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/setup.cfg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/setup.cfg b/ambari-common/src/main/python/ambari_jinja2/setup.cfg
new file mode 100644
index 0000000..2d74c58
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/setup.cfg
@@ -0,0 +1,6 @@
+[egg_info]
+tag_build = dev
+tag_date = true
+
+[aliases]
+release = egg_info -RDb ''

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/setup.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/setup.py b/ambari-common/src/main/python/ambari_jinja2/setup.py
new file mode 100644
index 0000000..7a7c242
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/setup.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+"""
+Jinja2
+~~~~~~
+
+Jinja2 is a template engine written in pure Python.  It provides a
+`Django`_ inspired non-XML syntax but supports inline expressions and
+an optional `sandboxed`_ environment.
+
+Nutshell
+--------
+
+Here a small example of a Jinja template::
+
+    {% extends 'base.html' %}
+    {% block title %}Memberlist{% endblock %}
+    {% block content %}
+      <ul>
+      {% for user in users %}
+        <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+      {% endfor %}
+      </ul>
+    {% endblock %}
+
+Philosophy
+----------
+
+Application logic is for the controller but don't try to make the life
+for the template designer too hard by giving him too few functionality.
+
+For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
+
+.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security)
+.. _Django: http://www.djangoproject.com/
+.. _Jinja2 webpage: http://jinja.pocoo.org/
+.. _documentation: http://jinja.pocoo.org/2/documentation/
+"""
+import sys
+
+from setuptools import setup, Extension, Feature
+
+debugsupport = Feature(
+    'optional C debug support',
+    standard=False,
+    ext_modules = [
+        Extension('ambari_jinja2._debugsupport', ['ambari_jinja2/_debugsupport.c']),
+    ],
+)
+
+
+# tell distribute to use 2to3 with our own fixers.
+extra = {}
+if sys.version_info >= (3, 0):
+    extra.update(
+        use_2to3=True,
+        use_2to3_fixers=['custom_fixers']
+    )
+
+# ignore the old '--with-speedups' flag
+try:
+    speedups_pos = sys.argv.index('--with-speedups')
+except ValueError:
+    pass
+else:
+    sys.argv[speedups_pos] = '--with-debugsupport'
+    sys.stderr.write('*' * 74 + '\n')
+    sys.stderr.write('WARNING:\n')
+    sys.stderr.write('  the --with-speedups flag is deprecated, assuming '
+                     '--with-debugsupport\n')
+    sys.stderr.write('  For the actual speedups install the MarkupSafe '
+                     'package.\n')
+    sys.stderr.write('*' * 74 + '\n')
+
+
+setup(
+    name='Jinja2',
+    version='2.5.5',
+    url='http://jinja.pocoo.org/',
+    license='BSD',
+    author='Armin Ronacher',
+    author_email='armin.ronacher@active-4.com',
+    description='A small but fast and easy to use stand-alone template '
+                'engine written in pure python.',
+    long_description=__doc__,
+    # jinja is egg safe. But we hate eggs
+    zip_safe=False,
+    classifiers=[
+        'Development Status :: 5 - Production/Stable',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 3',
+        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+        'Topic :: Text Processing :: Markup :: HTML'
+    ],
+    packages=['ambari_jinja2', 'ambari_jinja2.testsuite', 'ambari_jinja2.testsuite.res',
+              'ambari_jinja2._markupsafe'],
+    extras_require={'i18n': ['Babel>=0.8']},
+    test_suite='ambari_jinja2.testsuite.suite',
+    include_package_data=True,
+    entry_points="""
+    [babel.extractors]
+    ambari_jinja2 = ambari_jinja2.ext:babel_extract[i18n]
+    """,
+    features={'debugsupport': debugsupport},
+    **extra
+)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/AUTHORS
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/AUTHORS b/ambari-common/src/main/python/jinja2/AUTHORS
deleted file mode 100644
index c6cd9ba..0000000
--- a/ambari-common/src/main/python/jinja2/AUTHORS
+++ /dev/null
@@ -1,31 +0,0 @@
-Jinja is written and maintained by the Jinja Team and various
-contributors:
-
-Lead Developer:
-
-- Armin Ronacher <ar...@active-4.com>
-
-Developers:
-
-- Christoph Hack
-- Georg Brandl
-
-Contributors:
-
-- Bryan McLemore
-- Mickaël Guérin <ka...@crocobox.org>
-- Cameron Knight
-- Lawrence Journal-World.
-- David Cramer
-
-Patches and suggestions:
-
-- Ronny Pfannschmidt
-- Axel Böhm
-- Alexey Melchakov
-- Bryan McLemore
-- Clovis Fabricio (nosklo)
-- Cameron Knight
-- Peter van Dijk (Habbie)
-- Stefan Ebner
-- Rene Leonhardt

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/CHANGES
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/CHANGES b/ambari-common/src/main/python/jinja2/CHANGES
deleted file mode 100644
index 2a49c64..0000000
--- a/ambari-common/src/main/python/jinja2/CHANGES
+++ /dev/null
@@ -1,235 +0,0 @@
-Jinja2 Changelog
-================
-
-Version 2.5.5
--------------
-(re-release of 2.5.4 with built documentation removed for filesize.
- Released on October 18th 2010)
-
-- built documentation is no longer part of release.
-
-Version 2.5.4
--------------
-(bugfix release, released on October 17th 2010)
-
-- Fixed extensions not loading properly with overlays.
-- Work around a bug in cpython for the debugger that causes segfaults
-  on 64bit big-endian architectures.
-
-Version 2.5.3
--------------
-(bugfix release, released on October 17th 2010)
-
-- fixed an operator precedence error introduced in 2.5.2.  Statements
-  like "-foo.bar" had their implicit parentheses applied around the
-  first part of the expression ("(-foo).bar") instead of the more
-  correct "-(foo.bar)".
-
-Version 2.5.2
--------------
-(bugfix release, released on August 18th 2010)
-
-- improved setup.py script to better work with assumptions people
-  might still have from it (``--with-speedups``).
-- fixed a packaging error that excluded the new debug support.
-
-Version 2.5.1
--------------
-(bugfix release, released on August 17th 2010)
-
-- StopIteration exceptions raised by functions called from templates
-  are now intercepted and converted to undefineds.  This solves a
-  lot of debugging grief.  (StopIteration is used internally to
-  abort template execution)
-- improved performance of macro calls slightly.
-- babel extraction can now properly extract newstyle gettext calls.
-- using the variable `num` in newstyle gettext for something else
-  than the pluralize count will no longer raise a :exc:`KeyError`.
-- removed builtin markup class and switched to markupsafe.  For backwards
-  compatibility the pure Python implementation still exists but is
-  pulled from markupsafe by the Jinja2 developers.  The debug support
-  went into a separate feature called "debugsupport" and is disabled
-  by default because it is only relevant for Python 2.4
-- fixed an issue with unary operators having the wrong precendence.
-
-Version 2.5
------------
-(codename Incoherence, relased on May 29th 2010)
-
-- improved the sort filter (should have worked like this for a
-  long time) by adding support for case insensitive searches.
-- fixed a bug for getattribute constant folding.
-- support for newstyle gettext translations which result in a
-  nicer in-template user interface and more consistent
-  catalogs. (:ref:`newstyle-gettext`)
-- it's now possible to register extensions after an environment
-  was created.
-
-Version 2.4.1
--------------
-(bugfix release, released on April 20th 2010)
-
-- fixed an error reporting bug for undefineds.
-
-Version 2.4
------------
-(codename Correlation, released on April 13th 2010)
-
-- the environment template loading functions now transparently
-  pass through a template object if it was passed to it.  This
-  makes it possible to import or extend from a template object
-  that was passed to the template.
-- added a :class:`ModuleLoader` that can load templates from
-  precompiled sources.  The environment now features a method
-  to compile the templates from a configured loader into a zip
-  file or folder.
-- the _speedups C extension now supports Python 3.
-- added support for autoescaping toggling sections and support
-  for evaluation contexts (:ref:`eval-context`).
-- extensions have a priority now.
-
-Version 2.3.1
--------------
-(bugfix release, released on February 19th 2010)
-
-- fixed an error reporting bug on all python versions
-- fixed an error reporting bug on Python 2.4
-
-Version 2.3
------------
-(3000 Pythons, released on February 10th 2010)
-
-- fixes issue with code generator that causes unbound variables
-  to be generated if set was used in if-blocks and other small
-  identifier problems.
-- include tags are now able to select between multiple templates
-  and take the first that exists, if a list of templates is
-  given.
-- fixed a problem with having call blocks in outer scopes that
-  have an argument that is also used as local variable in an
-  inner frame (#360).
-- greatly improved error message reporting (#339)
-- implicit tuple expressions can no longer be totally empty.
-  This change makes ``{% if %}...{% endif %}`` a syntax error
-  now. (#364)
-- added support for translator comments if extracted via babel.
-- added with-statement extension.
-- experimental Python 3 support.
-
-Version 2.2.1
--------------
-(bugfix release, released on September 14th 2009)
-
-- fixes some smaller problems for Jinja2 on Jython.
-
-Version 2.2
------------
-(codename Kong, released on September 13th 2009)
-
-- Include statements can now be marked with ``ignore missing`` to skip
-  non existing templates.
-- Priority of `not` raised.  It's now possible to write `not foo in bar`
-  as an alias to `foo not in bar` like in python.  Previously the grammar
-  required parentheses (`not (foo in bar)`) which was odd.
-- Fixed a bug that caused syntax errors when defining macros or using the
-  `{% call %}` tag inside loops.
-- Fixed a bug in the parser that made ``{{ foo[1, 2] }}`` impossible.
-- Made it possible to refer to names from outer scopes in included templates
-  that were unused in the callers frame (#327)
-- Fixed a bug that caused internal errors if names where used as iteration
-  variable and regular variable *after* the loop if that variable was unused
-  *before* the loop.  (#331)
-- Added support for optional `scoped` modifier to blocks.
-- Added support for line-comments.
-- Added the `meta` module.
-- Renamed (undocumented) attribute "overlay" to "overlayed" on the
-  environment because it was clashing with a method of the same name.
-- speedup extension is now disabled by default.
-
-Version 2.1.1
--------------
-(Bugfix release)
-
-- Fixed a translation error caused by looping over empty recursive loops.
-
-Version 2.1
------------
-(codename Yasuzō, released on November 23rd 2008)
-
-- fixed a bug with nested loops and the special loop variable.  Before the
-  change an inner loop overwrote the loop variable from the outer one after
-  iteration.
-
-- fixed a bug with the i18n extension that caused the explicit pluralization
-  block to look up the wrong variable.
-
-- fixed a limitation in the lexer that made ``{{ foo.0.0 }}`` impossible.
-
-- index based subscribing of variables with a constant value returns an
-  undefined object now instead of raising an index error.  This was a bug
-  caused by eager optimizing.
-
-- the i18n extension looks up `foo.ugettext` now followed by `foo.gettext`
-  if an translations object is installed.  This makes dealing with custom
-  translations classes easier.
-
-- fixed a confusing behavior with conditional extending.  loops were partially
-  executed under some conditions even though they were not part of a visible
-  area.
-
-- added `sort` filter that works like `dictsort` but for arbitrary sequences.
-
-- fixed a bug with empty statements in macros.
-
-- implemented a bytecode cache system.  (:ref:`bytecode-cache`)
-
-- the template context is now weakref-able
-
-- inclusions and imports "with context" forward all variables now, not only
-  the initial context.
-
-- added a cycle helper called `cycler`.
-
-- added a joining helper called `joiner`.
-
-- added a `compile_expression` method to the environment that allows compiling
-  of Jinja expressions into callable Python objects.
-
-- fixed an escaping bug in urlize
-
-Version 2.0
------------
-(codename jinjavitus, released on July 17th 2008)
-
-- the subscribing of objects (looking up attributes and items) changed from
-  slightly.  It's now possible to give attributes or items a higher priority
-  by either using dot-notation lookup or the bracket syntax.  This also
-  changed the AST slightly.  `Subscript` is gone and was replaced with
-  :class:`~jinja2.nodes.Getitem` and :class:`~jinja2.nodes.Getattr`.
-
-  For more information see :ref:`the implementation details <notes-on-subscriptions>`.
-
-- added support for preprocessing and token stream filtering for extensions.
-  This would allow extensions to allow simplified gettext calls in template
-  data and something similar.
-
-- added :meth:`jinja2.environment.TemplateStream.dump`.
-
-- added missing support for implicit string literal concatenation.
-  ``{{ "foo" "bar" }}`` is equivalent to ``{{ "foobar" }}``
-
-- `else` is optional for conditional expressions.  If not given it evaluates
-  to `false`.
-
-- improved error reporting for undefined values by providing a position.
-
-- `filesizeformat` filter uses decimal prefixes now per default and can be
-  set to binary mode with the second parameter.
-
-- fixed bug in finalizer
-
-Version 2.0rc1
---------------
-(no codename, released on June 9th 2008)
-
-- first release of Jinja2

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/LICENSE
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/LICENSE b/ambari-common/src/main/python/jinja2/LICENSE
deleted file mode 100644
index 31bf900..0000000
--- a/ambari-common/src/main/python/jinja2/LICENSE
+++ /dev/null
@@ -1,31 +0,0 @@
-Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
-
-Some rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * The names of the contributors may not be used to endorse or
-      promote products derived from this software without specific
-      prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/MANIFEST.in
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/MANIFEST.in b/ambari-common/src/main/python/jinja2/MANIFEST.in
deleted file mode 100644
index aeb66af..0000000
--- a/ambari-common/src/main/python/jinja2/MANIFEST.in
+++ /dev/null
@@ -1,12 +0,0 @@
-include MANIFEST.in Makefile CHANGES LICENSE AUTHORS jinja2/_debugsupport.c
-recursive-include docs *
-recursive-include custom_fixers *
-recursive-include ext *
-recursive-include artwork *
-recursive-include examples *
-recursive-include jinja2/testsuite/res *
-recursive-exclude docs/_build *
-recursive-exclude jinja2 *.pyc
-recursive-exclude docs *.pyc
-recursive-exclude jinja2 *.pyo
-recursive-exclude docs *.pyo

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/Makefile b/ambari-common/src/main/python/jinja2/Makefile
deleted file mode 100644
index 60ca1d7..0000000
--- a/ambari-common/src/main/python/jinja2/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-test:
-	python setup.py test
-
-.PHONY: test

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg b/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg
deleted file mode 100644
index 0bc9ea4..0000000
--- a/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="300"
-   height="120"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   version="1.0"
-   sodipodi:docbase="/Users/mitsuhiko/Development/jinja2/artwork"
-   sodipodi:docname="jinjalogo.svg"
-   inkscape:export-filename="/Users/mitsuhiko/Development/jinja2/docs/_static/jinjabanner.png"
-   inkscape:export-xdpi="60"
-   inkscape:export-ydpi="60"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient6558">
-      <stop
-         style="stop-color:#575757;stop-opacity:1;"
-         offset="0"
-         id="stop6560" />
-      <stop
-         style="stop-color:#2f2f2f;stop-opacity:1;"
-         offset="1"
-         id="stop6562" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="radialGradient6564"
-       cx="61.297766"
-       cy="60.910986"
-       fx="61.297766"
-       fy="60.910986"
-       r="44.688254"
-       gradientTransform="matrix(1,0,0,0.945104,0,3.343747)"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="radialGradient6580"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,0.945104,0.355158,3.334402)"
-       cx="61.297766"
-       cy="60.910986"
-       fx="61.297766"
-       fy="60.910986"
-       r="44.688254" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="linearGradient4173"
-       x1="255.15521"
-       y1="32.347946"
-       x2="279.8912"
-       y2="32.347946"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.8073249,0,0,0.8073249,57.960878,7.4036303)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6558"
-       id="linearGradient5145"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.7902775,0,0,0.82474,60.019977,8.0684132)"
-       x1="255.15521"
-       y1="32.347946"
-       x2="279.8912"
-       y2="32.347946" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     gridtolerance="10000"
-     guidetolerance="10"
-     objecttolerance="10"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="2.8"
-     inkscape:cx="137.4752"
-     inkscape:cy="57.574575"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     width="300px"
-     height="120px"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1396"
-     inkscape:window-height="900"
-     inkscape:window-x="0"
-     inkscape:window-y="22" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       style="font-size:12px;font-style:normal;font-weight:normal;fill:#f4f4f4;fill-opacity:1;stroke:#e7e7e7;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;font-family:Bitstream Vera Sans;stroke-miterlimit:4;stroke-dasharray:none"
-       d="M 165.36463,80.874808 L 165.36463,80.874808 L 153.32556,80.874808 L 153.32556,81.8344 L 147.64994,81.8344 L 147.64994,36.035583 L 165.36463,36.035583 L 165.36463,20.333129 C 170.58154,21.031083 173.07533,22.077914 172.84609,23.473621 C 172.78871,24.055258 172.21545,24.549594 171.12624,24.956624 L 171.12624,36.035583 L 189.09895,36.035583 L 189.09895,82.532286 L 183.33733,82.532286 L 183.33733,80.874808 L 171.12624,80.874808 L 171.12624,102.94548 L 165.36463,102.94548 L 165.36463,80.874808 M 153.32556,55.489173 L 153.32556,55.489173 L 165.36463,55.489173 L 165.36463,41.793146 L 153.32556,41.793146 L 153.32556,55.489173 M 171.12624,55.489173 L 171.12624,55.489173 L 183.33733,55.489173 L 183.33733,41.793146 L 171.12624,41.793146 L 171.12624,55.489173 M 183.33733,61.333977 L 183.33733,61.333977 L 171.12624,61.333977 L 171.12624,75.030006 L 183.33733,75.030006 L 183.33733,61.333977 M 165.36463,61.333977 L 165.36463,61.333977 L 153.32556,61.333977 L 153.32556,75.030006 L 165.364
 63,75.030006 L 165.36463,61.333977 M 132.85897,59.414792 C 137.33069,63.136883 140.99969,67.934848 143.86618,73.808701 L 139.13654,77.385372 C 137.24467,72.965445 134.6362,69.12707 131.31114,65.87024 L 131.31114,102.94548 L 125.63554,102.94548 L 125.63554,68.57455 C 122.31042,71.947693 118.52671,74.913707 114.28436,77.47261 L 109.64069,73.372526 C 121.50782,67.091566 130.62312,55.489212 136.98668,38.565417 L 116.26221,38.565417 L 116.26221,32.720615 L 125.80754,32.720615 L 125.80754,20.333129 C 130.85245,21.031083 133.31761,22.048838 133.20299,23.386383 C 133.14561,24.026183 132.57235,24.549594 131.48307,24.956624 L 131.48307,32.720615 L 140.77043,32.720615 L 143.60824,36.733469 C 140.68444,45.51526 137.10137,53.075692 132.85897,59.414792 M 254.11016,49.469901 L 254.11016,49.469901 L 254.11016,20.333129 C 259.21243,21.031083 261.67755,22.048838 261.50562,23.386383 C 261.44823,23.909869 261.04699,24.346044 260.30172,24.694917 C 260.30164,24.694986 260.30164,24.694986 260.30172,24.694
 917 L 260.30172,24.694917 L 259.78578,24.956624 L 259.78578,49.469901 L 277.15652,49.469901 L 277.15652,55.227471 L 259.78578,55.227471 L 259.78578,93.785712 L 281.45616,93.785712 L 281.45616,99.63051 L 232.35378,99.63051 L 232.35378,93.785712 L 254.11016,93.785712 L 254.11016,55.227471 L 236.22346,55.227471 L 236.22346,49.469901 L 254.11016,49.469901 M 225.5603,59.327554 C 231.12111,63.107798 235.62145,67.876693 239.06127,73.634235 L 234.76157,77.647079 C 231.60845,72.180322 227.82475,67.934848 223.41044,64.910648 L 223.41044,102.94548 L 217.73484,102.94548 L 217.73484,67.44049 C 212.91919,71.627831 207.70222,75.030021 202.084,77.647079 L 197.87027,73.198053 C 212.66118,66.917101 224.01239,55.372897 231.92377,38.565417 L 205.35172,38.565417 L 205.35172,32.720615 L 217.99283,32.720615 L 217.99283,20.333129 C 223.03774,21.031083 225.50291,22.048838 225.38829,23.386383 C 225.33089,24.026183 224.75765,24.549594 223.66837,24.956624 L 223.66837,32.720615 L 236.22346,32.720615 L 238.80326
 ,36.733469 C 235.13421,45.51526 230.71987,53.046611 225.5603,59.327554"
-       id="text4761" />
-    <path
-       style="font-size:44.09793472px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#b41717;fill-opacity:1;stroke:#7f2828;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Candara;stroke-miterlimit:4;stroke-dasharray:none"
-       d="M 149.14708,37.774469 C 148.97807,41.117899 148.84526,44.824225 148.74871,48.893456 C 148.67626,52.962754 148.3818,70.641328 148.38184,75.524422 C 148.3818,79.065795 148.05588,81.991266 147.40406,84.300835 C 146.75219,86.610422 145.72612,88.557071 144.32585,90.140779 C 142.94969,91.724494 141.17522,92.901283 139.00239,93.671139 C 136.82953,94.440996 134.22211,94.825935 131.18014,94.825935 C 128.83828,94.825935 126.73787,94.59498 124.87889,94.133049 L 125.4221,89.31593 C 127.13623,90.0418 128.92278,90.404734 130.78177,90.404733 C 132.85805,90.404734 134.66875,90.140782 136.2139,89.612876 C 137.78315,89.062981 139.02651,88.216133 139.94396,87.072335 C 140.8855,85.928548 141.54942,84.520804 141.93572,82.8491 C 142.34613,81.177412 142.55134,78.988811 142.55136,76.283285 C 142.55134,66.297119 142.62852,44.659257 142.26641,37.774469 L 149.14708,37.774469 M 166.38498,80.732697 L 159.83024,80.732697 C 160.16821,76.333498 160.33723,71.307412 160.33723,65.654424 C 160.33723,59.2976 
 159.91471,53.963567 159.06973,49.652319 L 166.31257,48.761483 C 166.02284,53.358679 165.87799,58.98965 165.87799,65.654424 C 165.87799,70.933479 166.04699,75.959565 166.38498,80.732697 M 167.90601,39.490159 C 167.90598,40.611994 167.5076,41.590815 166.7109,42.42662 C 165.91418,43.240515 164.79155,43.647442 163.343,43.647399 C 162.11172,43.647442 161.146,43.295504 160.44588,42.591595 C 159.76988,41.865769 159.43188,40.996927 159.43188,39.98507 C 159.43188,38.885304 159.84231,37.928485 160.66315,37.114591 C 161.48399,36.30078 162.61869,35.893853 164.06727,35.893811 C 165.25023,35.893853 166.17975,36.256783 166.85575,36.982609 C 167.55588,37.686526 167.90598,38.522373 167.90601,39.490159 M 206.72748,80.732697 L 200.13651,80.732697 C 200.66763,74.947749 200.93319,68.634899 200.9332,61.794122 C 200.93319,58.406756 200.1727,56.097177 198.65174,54.865371 C 197.15487,53.61163 195.00619,52.984747 192.20564,52.984714 C 188.77731,52.984747 185.61465,54.117535 182.71753,56.383099 C 182.71753,63
 .883761 182.76583,72.000287 182.86238,80.732697 L 176.27142,80.732697 C 176.68182,73.254058 176.88707,67.843042 176.88707,64.499632 C 176.88707,59.352589 176.3559,54.359493 175.29363,49.520339 L 181.66734,48.695493 L 182.35539,52.720761 L 182.64511,52.720761 C 186.21823,49.773323 190.04483,48.299592 194.12499,48.299567 C 198.13265,48.299592 201.23499,49.113454 203.43201,50.741118 C 205.62895,52.346863 206.72747,55.217334 206.72748,59.352563 C 206.72747,59.770507 206.70331,60.595362 206.65507,61.827118 C 206.60675,63.058915 206.5826,63.883761 206.58262,64.30167 C 206.5826,67.975018 206.63088,73.452022 206.72748,80.732697 M 222.69791,48.695493 C 222.28747,55.514282 222.08225,62.355041 222.08225,69.21778 C 222.08225,71.043461 222.14262,73.463019 222.26332,76.476468 C 222.40822,79.467925 222.4806,81.502559 222.48063,82.580363 C 222.4806,89.685068 219.51105,93.996287 213.57195,95.514024 L 211.76124,93.006484 C 213.90995,91.356766 215.2378,89.597085 215.74478,87.727431 C 216.49321,85.0439
 12 216.86743,79.324953 216.86743,70.570535 C 216.86743,61.178248 216.3846,54.16153 215.41887,49.520339 L 222.69791,48.695493 M 224.2551,39.490159 C 224.2551,40.611994 223.85673,41.590815 223.06006,42.42662 C 222.26332,43.240515 221.14069,43.647442 219.69213,43.647399 C 218.46084,43.647442 217.49515,43.295504 216.795,42.591595 C 216.119,41.865769 215.781,40.996927 215.781,39.98507 C 215.781,38.885304 216.19144,37.928485 217.01231,37.114591 C 217.83316,36.30078 218.96785,35.893853 220.4164,35.893811 C 221.5994,35.893853 222.52889,36.256783 223.20492,36.982609 C 223.90503,37.686526 224.2551,38.522373 224.2551,39.490159 M 259.60008,80.732697 L 253.91446,80.930661 C 253.62473,79.852857 253.47987,78.830045 253.4799,77.862216 L 253.11774,77.862216 C 250.14817,80.325772 246.10427,81.557546 240.98606,81.557547 C 238.20962,81.557546 235.8195,80.820682 233.81563,79.346948 C 231.81178,77.851221 230.80988,75.728607 230.80988,72.979099 C 230.80988,69.591724 232.37914,66.875216 235.51769,64.829574
  C 238.65625,62.761967 244.48667,61.67316 253.00913,61.563165 C 253.08155,61.035275 253.11772,60.430386 253.11774,59.748497 C 253.11772,57.043003 252.32104,55.239336 250.72765,54.337474 C 249.15832,53.435661 246.76819,52.984747 243.55721,52.984714 C 239.76681,52.984747 236.03678,53.413668 232.3671,54.271484 L 232.9827,49.718301 C 236.60411,48.77251 240.76873,48.299592 245.47658,48.299567 C 249.77395,48.299592 253.09359,49.113454 255.43545,50.741118 C 257.77728,52.346863 258.94819,55.096363 258.94824,58.989625 C 258.94819,60.023469 258.88785,61.904117 258.76715,64.631608 C 258.67054,67.337133 258.62228,69.140806 258.6223,70.042632 C 258.62228,74.045913 258.94819,77.609265 259.60008,80.732697 M 253.19019,74.331856 C 253.06945,70.988469 253.00909,67.986016 253.00913,65.324484 C 248.47027,65.324498 245.01786,65.632443 242.65187,66.248318 C 238.69248,67.348131 236.71278,69.448748 236.71278,72.550177 C 236.71278,75.541643 239.03044,77.037371 243.66588,77.037366 C 247.64942,77.037371 250.8
 2416,76.135534 253.19019,74.331856"
-       id="text3736"
-       sodipodi:nodetypes="ccsscssccscccsccccsccsccsscsssccccscscccsccccscsssccscscccscccsscsssccccccscsccscsccscscsccccssc" />
-    <path
-       style="fill:url(#radialGradient6564);fill-opacity:1.0;fill-rule:evenodd;stroke:#323232;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
-       d="M 105.45673,18.675923 C 105.45673,18.675923 88.211949,26.918461 74.172834,28.737898 C 60.133727,30.557333 33.360434,32.377571 28.045622,31.093256 C 22.730818,29.808941 18.915645,28.309196 18.915645,28.309196 L 20.021441,32.056583 L 16.609513,35.052471 L 17.2144,36.121726 L 18.61792,36.22764 L 22.92773,36.762252 L 23.532621,38.688909 L 25.937975,38.905784 L 27.143021,42.970927 C 27.143021,42.970927 32.254764,43.399628 33.758953,43.399628 C 35.263142,43.399628 38.271966,43.187802 38.271966,43.187802 L 38.371202,44.791657 L 39.477002,45.003495 L 39.477002,46.824227 L 37.066917,48.967759 L 37.671807,49.073671 L 37.671807,49.820127 C 37.671807,49.820127 32.255457,50.252157 30.049301,49.93109 C 27.843157,49.610006 27.440747,49.608286 27.440747,49.608286 L 27.242258,49.820127 L 27.143021,50.783455 L 27.643946,50.783455 L 27.84242,54.959544 L 38.976091,54.530844 L 38.172728,68.980747 L 38.073481,70.796442 L 28.645781,70.261816 L 28.546544,66.408513 L 30.649462,66.408513 L 30.85267
 3,64.910557 L 32.757107,64.481857 L 33.059555,64.058192 L 25.937975,62.343374 L 20.522364,63.947229 L 21.42496,64.698732 L 22.327572,64.698732 L 22.426809,65.984848 L 24.331254,66.09076 L 24.331254,69.838147 L 22.228335,70.372777 L 22.630009,71.225146 L 23.130934,71.547931 L 23.130934,74.437917 L 24.435218,74.437917 L 24.435218,87.813529 L 22.327572,88.13632 L 22.630009,91.989617 L 23.929569,92.206492 L 23.731093,100.98236 L 29.449141,101.08826 L 28.244105,92.418334 L 36.868446,92.206492 L 36.268285,96.912181 L 35.464925,100.23086 L 44.188501,100.33677 L 44.287739,91.777793 L 50.303506,91.243181 L 50.005786,96.700351 L 49.802585,99.90807 L 54.920484,99.90807 L 54.717274,91.132217 L 55.421397,91.243181 L 55.619882,87.067076 L 54.816521,87.067076 L 54.518798,85.352258 L 54.017874,80.429702 L 54.216359,74.760706 L 55.31743,74.760706 L 55.31743,71.336105 L 53.913913,71.442015 L 54.117112,67.402096 L 55.747469,67.240708 L 55.823083,65.929374 L 56.749319,65.793192 L 57.699176,65.071956 L 
 51.985842,63.896802 L 46.31977,65.15265 L 46.872668,66.060507 L 47.47283,66.010066 L 48.172228,65.984848 L 48.299828,67.639144 L 49.878196,67.563497 L 49.906548,71.144447 L 43.111042,70.988097 L 43.337879,67.160002 L 43.559978,63.679927 L 43.559978,59.105378 L 43.763188,54.288748 L 57.373101,53.592733 L 73.567955,52.659674 L 73.71917,55.736265 L 73.142647,63.120082 L 72.892183,69.9945 L 66.928387,69.888585 L 66.900039,65.071956 L 69.106918,64.991267 L 69.206169,63.629486 L 70.108765,63.493308 L 70.061506,63.226006 L 70.964116,63.175568 L 71.465028,62.504773 L 64.721507,60.926122 L 58.001612,62.368592 L 58.4789,63.200785 L 59.230285,63.1453 L 59.230285,63.523577 L 60.156518,63.523577 L 60.156518,65.046738 L 62.136575,65.071956 L 62.112937,69.298485 L 60.109259,69.298485 L 60.080907,70.261816 L 60.785031,70.342507 L 60.70942,74.009202 L 62.188552,74.089909 L 62.013701,88.620507 L 60.057282,89.018952 L 60.080907,89.714967 L 60.761406,89.714967 L 60.761406,93.437137 L 61.886113,93.43713
 7 L 61.588391,98.52109 L 61.210343,102.95945 L 68.331912,103.14605 L 68.105084,99.29275 L 67.580538,96.085028 L 67.476575,93.300955 L 73.520696,93.195041 L 73.345845,97.502272 L 73.317494,102.05159 L 76.729426,102.3189 L 81.3653,102.1323 L 82.820807,101.70358 L 82.017437,99.26753 L 81.818959,95.439438 L 81.440912,92.710853 L 87.206218,92.499027 L 86.955759,95.842931 L 86.932133,101.08826 L 89.238253,101.30009 L 91.520751,101.24965 L 92.621828,100.90165 L 91.969693,95.923633 L 91.747577,92.176239 L 92.725793,92.070324 L 92.749427,88.726422 L 93.02352,88.670945 L 92.976244,87.949712 L 91.846823,87.949712 L 91.619996,85.488427 L 91.520751,74.811143 L 92.371377,74.785924 L 92.371377,71.280616 L 92.725793,71.336105 L 92.725793,70.640088 L 91.468773,70.529127 L 91.497126,66.463987 L 93.600043,66.277382 L 93.477182,64.910557 L 94.403419,64.829863 L 94.351424,64.562549 L 95.580099,63.947229 L 89.337489,62.69138 L 82.995657,63.977495 L 83.39733,64.723951 L 84.375543,64.643256 L 84.427528,64.
 966046 L 85.254515,64.966046 L 85.301775,66.569901 L 87.357445,66.544681 L 87.532293,70.478688 L 80.264217,70.423216 L 79.413593,64.512124 L 78.733106,61.380041 L 78.184923,55.761484 L 78.510996,52.473053 L 92.999878,51.373557 L 93.047136,46.476221 L 93.774891,46.289613 L 93.727651,45.543159 L 93.174743,45.220372 C 93.174629,45.220372 85.252181,46.395266 82.745197,46.66284 C 82.0389,46.738209 82.09239,46.733258 81.516524,46.79397 L 81.440912,45.886118 L 78.444837,44.317564 L 78.482644,42.491786 L 79.512842,42.461518 L 79.588444,39.949808 C 79.588444,39.949808 85.728225,39.546834 88.009582,39.0117 C 90.290937,38.476559 93.524432,37.942456 93.524432,37.942456 L 95.055545,33.79662 L 98.089437,32.913987 L 98.339888,32.217972 L 105.20628,30.316548 L 105.98602,29.676006 L 103.37744,23.976741 L 103.62792,22.690624 L 104.95584,21.994611 L 105.91041,19.079404 L 105.45673,18.675923 z M 72.466874,40.403728 L 72.429067,42.476654 L 73.983813,42.542211 L 73.884576,44.509221 L 70.836515,46.506487 
 L 70.647496,47.081457 L 71.876167,47.091543 L 71.866712,47.575729 L 62.552432,48.029652 L 62.613863,46.652742 L 63.039175,45.966809 L 63.067524,45.528025 L 63.07698,44.579832 L 63.341609,43.949374 L 63.440849,43.439982 L 63.440849,43.076841 L 63.842533,41.47297 L 72.466874,40.403728 z M 52.987688,42.168984 L 52.760853,43.561027 L 53.488599,44.418431 L 53.441349,45.916386 L 54.117112,46.960408 L 53.942262,48.191039 L 54.443185,48.912273 L 44.939872,49.2855 L 44.916247,48.967759 L 46.017333,48.831579 L 46.069307,48.428097 L 43.66394,47.121797 L 43.536351,45.03375 L 44.689411,44.978276 L 44.788661,42.72883 L 52.987688,42.168984 z M 67.051262,74.276518 L 72.81657,74.649742 L 72.618099,82.411833 L 73.36947,88.776857 L 67.254465,88.565018 L 67.051262,74.276518 z M 28.44258,74.599304 L 37.671807,75.078442 L 36.868446,80.429702 L 36.868446,84.928593 L 37.520583,87.440302 L 28.494569,87.869006 L 28.44258,74.599304 z M 87.508658,74.649742 L 87.508658,87.924488 L 81.644113,88.353194 L 81.44091
 2,81.342592 L 80.788764,74.811143 L 87.508658,74.649742 z M 43.087416,74.947312 L 49.906548,74.972531 L 49.977434,87.278902 L 43.611966,87.389863 L 43.285891,83.400379 L 43.262266,79.441156 L 43.087416,74.947312 z "
-       id="path4735" />
-  </g>
-</svg>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/custom_fixers/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/__init__.py b/ambari-common/src/main/python/jinja2/custom_fixers/__init__.py
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py b/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py
deleted file mode 100644
index 96a81c1..0000000
--- a/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from lib2to3 import fixer_base
-from lib2to3.fixer_util import Name, BlankLine
-
-
-class FixAltUnicode(fixer_base.BaseFix):
-    PATTERN = """
-    func=funcdef< 'def' name='__unicode__'
-                  parameters< '(' NAME ')' > any+ >
-    """
-
-    def transform(self, node, results):
-        name = results['name']
-        name.replace(Name('__str__', prefix=name.prefix))

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py b/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py
deleted file mode 100644
index fd0ea68..0000000
--- a/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from lib2to3 import fixer_base, pytree
-from lib2to3.fixer_util import Name, BlankLine, Name, Attr, ArgList
-
-
-class FixBrokenReraising(fixer_base.BaseFix):
-    PATTERN = """
-    raise_stmt< 'raise' any ',' val=any ',' tb=any >
-    """
-
-    # run before the broken 2to3 checker with the same goal
-    # tries to rewrite it with a rule that does not work out for jinja
-    run_order = 1
-
-    def transform(self, node, results):
-        tb = results['tb'].clone()
-        tb.prefix = ''
-        with_tb = Attr(results['val'].clone(), Name('with_traceback')) + \
-                  [ArgList([tb])]
-        new = pytree.Node(self.syms.simple_stmt, [Name("raise")] + with_tb)
-        new.prefix = node.prefix
-        return new

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py b/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py
deleted file mode 100644
index 5d35e50..0000000
--- a/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from lib2to3 import fixer_base
-from lib2to3.fixer_util import Name, BlankLine
-
-
-# whyever this is necessary..
-
-class FixXrange2(fixer_base.BaseFix):
-    PATTERN = "'xrange'"
-
-    def transform(self, node, results):
-        node.replace(Name('range', prefix=node.prefix))

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/Makefile b/ambari-common/src/main/python/jinja2/docs/Makefile
deleted file mode 100644
index 5e24ec1..0000000
--- a/ambari-common/src/main/python/jinja2/docs/Makefile
+++ /dev/null
@@ -1,75 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
-
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
-
-help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  html      to make standalone HTML files"
-	@echo "  pickle    to make pickle files"
-	@echo "  json      to make JSON files"
-	@echo "  htmlhelp  to make HTML files and a HTML help project"
-	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  changes   to make an overview over all changed/added/deprecated items"
-	@echo "  linkcheck to check all external links for integrity"
-
-clean:
-	-rm -rf _build/*
-
-html:
-	mkdir -p _build/html _build/doctrees
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
-	@echo
-	@echo "Build finished. The HTML pages are in _build/html."
-
-pickle:
-	mkdir -p _build/pickle _build/doctrees
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files"
-
-json:
-	mkdir -p _build/json _build/doctrees
-	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
-	@echo
-	@echo "Build finished; now you can process the json files"
-
-web: pickle
-
-htmlhelp:
-	mkdir -p _build/htmlhelp _build/doctrees
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in _build/htmlhelp."
-
-latex:
-	mkdir -p _build/latex _build/doctrees
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in _build/latex."
-	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
-	      "run these through (pdf)latex."
-
-changes:
-	mkdir -p _build/changes _build/doctrees
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
-	@echo
-	@echo "The overview file is in _build/changes."
-
-linkcheck:
-	mkdir -p _build/linkcheck _build/doctrees
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in _build/linkcheck/output.txt."

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_build/.ignore
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_build/.ignore b/ambari-common/src/main/python/jinja2/docs/_build/.ignore
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_static/.ignore
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/.ignore b/ambari-common/src/main/python/jinja2/docs/_static/.ignore
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_static/jinja.js
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/jinja.js b/ambari-common/src/main/python/jinja2/docs/_static/jinja.js
deleted file mode 100644
index 1c04218..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_static/jinja.js
+++ /dev/null
@@ -1,26 +0,0 @@
-$(function() {
-
-  var
-    toc = $('#toc').show(),
-    items = $('#toc > ul').hide();
-
-  $('#toc h3')
-    .click(function() {
-      if (items.is(':visible')) {
-        items.animate({
-          height:     'hide',
-          opacity:    'hide'
-        }, 300, function() {
-          toc.removeClass('expandedtoc');
-        });
-      }
-      else {
-        items.animate({
-          height:     'show',
-          opacity:    'show'
-        }, 400);
-        toc.addClass('expandedtoc');
-      }
-    });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_static/print.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/print.css b/ambari-common/src/main/python/jinja2/docs/_static/print.css
deleted file mode 100644
index fb633d8..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_static/print.css
+++ /dev/null
@@ -1,5 +0,0 @@
-div.header, div.relnav, #toc { display: none; }
-#contentwrapper { padding: 0; margin: 0; border: none; }
-body { color: black; background-color: white; }
-div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
-div.footer a { text-decoration: none; }

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_static/style.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/style.css b/ambari-common/src/main/python/jinja2/docs/_static/style.css
deleted file mode 100644
index a1c4d59..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_static/style.css
+++ /dev/null
@@ -1,390 +0,0 @@
-body {
-    background-color: #222;
-    margin: 0;
-    padding: 0;
-    font-family: 'Georgia', serif;
-    font-size: 15px;
-    color: #eee;
-}
-
-div.footer {
-    border-top: 1px solid #111;
-    padding: 8px;
-    font-size: 11px;
-    text-align: center;
-    letter-spacing: 0.5px;
-}
-
-div.footer a {
-    color: #eee;
-}
-
-div.header {
-    margin: 0 -15px 0 -15px;
-    background: url(headerbg.png) repeat-x;
-    border-top: 6px solid #D20000;
-}
-
-div.relnav {
-    border-bottom: 1px solid #111;
-    background: url(navigation.png);
-    margin: 0 -15px 0 -15px;
-    padding: 2px 20px 0 28px;
-    line-height: 25px;
-    color: #aaa;
-    font-size: 12px;
-    text-align: center;
-}
-
-div.relnav a {
-    color: #eee;
-    font-weight: bold;
-    text-decoration: none;
-}
-
-div.relnav a:hover {
-    text-decoration: underline;
-}
-
-#content {
-    background-color: white;
-    color: #111;
-    border-bottom: 1px solid black;
-    background: url(watermark.png) center 0;
-    padding: 0 15px 0 15px;
-    margin: 0;
-}
-
-h1 {
-    margin: 0;
-    padding: 15px 0 0 0;
-}
-
-h1.heading {
-    margin: 0;
-    padding: 0;
-    height: 80px;
-}
-
-h1.heading:hover {
-    background: #222;
-}
-
-h1.heading a {
-    background: url(jinjabanner.png) no-repeat center 0;
-    display: block;
-    width: 100%;
-    height: 80px;
-}
-
-h1.heading a:focus {
-    -moz-outline: none;
-    outline: none;
-}
-
-h1.heading span {
-    display: none;
-}
-
-#jinjalogo {
-    background-image: url(jinjalogo.png);
-    background-repeat: no-repeat;
-    width: 400px;
-    height: 160px;
-}
-
-#contentwrapper {
-    max-width: 680px;
-    padding: 0 18px 20px 18px;
-    margin: 0 auto 0 auto;
-    border-right: 1px solid #eee;
-    border-left: 1px solid #eee;
-    background: url(watermark_blur.png) center -114px;
-}
-
-#contentwrapper h2,
-#contentwrapper h2 a {
-    color: #222;
-    font-size: 24px;
-    margin: 20px 0 0 0;
-}
-
-#contentwrapper h3,
-#contentwrapper h3 a {
-    color: #b41717;
-    font-size: 20px;
-    margin: 20px 0 0 0;
-}
-
-table.docutils {
-    border-collapse: collapse;
-    border: 2px solid #aaa;
-    margin: 0.5em 1.5em 0.5em 1.5em;
-}
-
-table.docutils td {
-    padding: 2px;
-    border: 1px solid #ddd;
-}
-
-p, li, dd, dt, blockquote {
-    color: #333;
-}
-
-blockquote {
-    margin: 10px 0 10px 20px;
-}
-
-p {
-    line-height: 20px;
-    margin-bottom: 0;
-    margin-top: 10px;
-}
-
-hr {
-    border-top: 1px solid #ccc;
-    border-bottom: 0;
-    border-right: 0;
-    border-left: 0;
-    margin-bottom: 10px;
-    margin-top: 20px;
-}
-
-dl {
-    margin-left: 10px;
-}
-
-li, dt {
-    margin-top: 5px;
-}
-
-dt {
-    font-weight: bold;
-    color: #000;
-}
-
-dd {
-    margin-top: 10px;
-    line-height: 20px;
-}
-
-th {
-    text-align: left;
-    padding: 3px;
-    background-color: #f2f2f2;
-}
-
-a {
-    color: #b41717;
-}
-
-a:hover {
-    color: #444;
-}
-
-pre {
-    background: #ededed url(metal.png);
-    border-top: 1px solid #ccc;
-    border-bottom: 1px solid #ccc;
-    padding: 5px;
-    font-size: 13px;
-    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
-}
-
-tt {
-    font-size: 13px;
-    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
-    color: black;
-    padding: 1px 2px 1px 2px;
-    background-color: #fafafa;
-    border-bottom: 1px solid #eee;
-}
-
-a.reference:hover tt {
-    border-bottom-color: #aaa;
-}
-
-cite {
-    /* abusing <cite>, it's generated by ReST for `x` */
-    font-size: 13px;
-    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
-    font-weight: bold;
-    font-style: normal;
-}
-
-div.admonition {
-    margin: 10px 0 10px 0;
-    padding: 10px 10px 10px 60px;
-    border: 1px solid #ccc;
-}
-
-div.admonition p.admonition-title {
-    background-color: #b41717;
-    color: white;
-    margin: -10px -10px 10px -60px;
-    padding: 4px 10px 4px 10px;
-    font-weight: bold;
-    font-size: 15px;
-}
-
-div.admonition p.admonition-title a {
-    color: white!important;
-}
-
-div.admonition-note {
-    background: url(note.png) no-repeat 10px 40px;
-}
-
-div.admonition-implementation {
-    background: url(implementation.png) no-repeat 10px 40px;
-}
-
-a.headerlink {
-    color: #B4B4B4!important;
-    font-size: 0.8em;
-    padding: 0 4px 0 4px;
-    text-decoration: none!important;
-    visibility: hidden;
-}
-
-h1:hover > a.headerlink,
-h2:hover > a.headerlink,
-h3:hover > a.headerlink,
-h4:hover > a.headerlink,
-h5:hover > a.headerlink,
-h6:hover > a.headerlink,
-dt:hover > a.headerlink,
-dt:hover > a.headerlink {
-    visibility: visible;
-}
-
-a.headerlink:hover {
-    background-color: #B4B4B4;
-    color: #F0F0F0!important;
-}
-
-table.indextable {
-    width: 100%;
-}
-
-table.indextable td {
-    vertical-align: top;
-    width: 50%;
-}
-
-table.indextable dl dd {
-    font-size: 11px;
-}
-
-table.indextable dl dd a {
-    color: #000;
-}
-
-dl.function dt,
-dl.class dt,
-dl.exception dt,
-dl.method dt,
-dl.attribute dt {
-    font-weight: normal;
-}
-
-dt .descname {
-    font-weight: bold;
-    margin-right: 4px;
-}
-
-dt .descname, dt .descclassname {
-    padding: 0;
-    background: transparent;
-    border-bottom: 1px solid #111;
-}
-
-dt .descclassname {
-    margin-left: 2px;
-}
-
-dl dt big {
-    font-size: 100%;
-}
-
-ul.search {
-    margin: 10px 0 0 30px;
-    padding: 0;
-}
-
-ul.search li {
-    margin: 10px 0 0 0;
-    padding: 0;
-}
-
-ul.search div.context {
-    font-size: 12px;
-    padding: 4px 0 0 20px;
-    color: #888;
-}
-
-span.highlight {
-    background-color: #eee;
-    border: 1px solid #ccc;
-}
-
-#toc {
-    margin: 0 -17px 0 -17px;
-    display: none;
-}
-
-#toc h3 {
-    float: right;
-    margin: 5px 5px 0 0;
-    padding: 0;
-    font-size: 12px;
-    color: #777;
-}
-
-#toc h3:hover {
-    color: #333;
-    cursor: pointer;
-}
-
-.expandedtoc {
-    background: #222 url(darkmetal.png);
-    border-bottom: 1px solid #111;
-    outline-bottom: 1px solid #000;
-    padding: 5px;
-}
-
-.expandedtoc h3 {
-    color: #aaa;
-    margin: 0!important;
-}
-
-.expandedtoc h3:hover {
-    color: white!important;
-}
-
-#tod h3:hover {
-    color: white;
-}
-
-#toc a {
-    color: #ddd;
-    text-decoration: none;
-}
-
-#toc a:hover {
-    color: white;
-    text-decoration: underline;
-}
-
-#toc ul {
-    margin: 5px 0 12px 17px;
-    padding: 0 7px 0 7px;
-}
-
-#toc ul ul {
-    margin-bottom: 0;
-}
-
-#toc ul li {
-    margin: 2px 0 0 0;
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_templates/.ignore
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/.ignore b/ambari-common/src/main/python/jinja2/docs/_templates/.ignore
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html b/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html
deleted file mode 100644
index 9add6e9..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html
+++ /dev/null
@@ -1,36 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Index' %}
-{% block body %}
-
-  <h1 id="index">Index</h1>
-
-  {% for key, dummy in genindexentries -%}
-  <a href="#{{ key }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %}
-  {%- endfor %}
-  <hr>
-
-  {% for key, entries in genindexentries %}
-    <h2 id="{{ key }}">{{ key }}</h2>
-    <table class="indextable"><tr>
-    {%- for column in entries|slice(2) if column %}
-      <td><dl>
-      {%- for entryname, (links, subitems) in column %}
-        <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
-          {% for link in links[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor %}
-          {%- else %}{{ entryname|e }}{% endif %}</dt>
-        {%- if subitems %}
-        <dd><dl>
-          {%- for subentryname, subentrylinks in subitems %}
-          <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
-          {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor -%}
-          </dt>
-          {%- endfor %}
-        </dl></dd>
-        {%- endif -%}
-      {%- endfor %}
-      </dl></td>
-    {%- endfor %}
-    </tr></table>
-  {% endfor %}
-
-{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/layout.html b/ambari-common/src/main/python/jinja2/docs/_templates/layout.html
deleted file mode 100644
index f682f90..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_templates/layout.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-  <head>
-    <title>Jinja2 Documentation</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}" type="text/css">
-    <link rel="stylesheet" href="{{ pathto('_static/print.css', 1) }}" type="text/css" media="print">
-    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css">
-    {%- if builder != 'htmlhelp' %}
-    <script type="text/javascript">
-      var DOCUMENTATION_OPTIONS = {
-        URL_ROOT:   '{{ pathto("", 1) }}',
-        VERSION:    '{{ release }}'
-      };
-    </script>
-    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/jinja.js', 1) }}"></script>
-    {%- endif %}
-    {%- if use_opensearch and builder != 'htmlhelp' %}
-    <link rel="search" type="application/opensearchdescription+xml"
-          title="Search within {{ docstitle }}"
-          href="{{ pathto('_static/opensearch.xml', 1) }}">
-    {%- endif %}
-    {%- if hasdoc('about') %}
-    <link rel="author" title="About these documents" href="{{ pathto('about') }}">
-    {%- endif %}
-    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}">
-    <link rel="index" title="Global index" href="{{ pathto('genindex') }}">
-    <link rel="search" title="Search" href="{{ pathto('search') }}">
-    {%- if hasdoc('copyright') %}
-    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}">
-    {%- endif %}
-    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}">
-    {%- if parents %}
-    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}">
-    {%- endif %}
-    {%- if next %}
-    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}">
-    {%- endif %}
-    {%- if prev %}
-    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}">
-    {%- endif %}
-    {% block extrahead %}{% endblock %}
-  </head>
-  <body>
-    <div id="content">
-      <div class="header">
-        <h1 class="heading"><a href="{{ pathto('index') }}"
-          title="back to the documentation overview"><span>Jinja</span></a></h1>
-      </div>
-      <div class="relnav">
-        {%- if prev %}
-        <a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
-        {%- endif %}
-        <a href="{{ pathto(current_page_name) if current_page_name else '#' }}">{{ title }}</a>
-        {%- if next %}
-        | <a href="{{ next.link|e }}">{{ next.title }} &raquo;</a>
-        {%- endif %}
-      </div>
-      <div id="contentwrapper">
-        {%- if display_toc %}
-        <div id="toc">
-          <h3>Table Of Contents</h3>
-          {{ toc }}
-        </div>
-        {%- endif %}
-        {% block body %}{% endblock %}
-      </div>
-    </div>
-    <div class="footer">
-      © Copyright 2010 by the <a href="http://pocoo.org/">Pocoo Team</a>,
-      documentation generated by <a href="http://sphinx.pocoo.org/">Sphinx</a>
-    </div>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml b/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml
deleted file mode 100644
index 9f2fa42..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
-  <ShortName>{{ project }}</ShortName>
-  <Description>Search {{ docstitle }}</Description>
-  <InputEncoding>utf-8</InputEncoding>
-  <Url type="text/html" method="get"
-       template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&amp;check_keywords=yes&amp;area=default"/>
-  <LongName>{{ docstitle }}</LongName>
-</OpenSearchDescription>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_templates/page.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/page.html b/ambari-common/src/main/python/jinja2/docs/_templates/page.html
deleted file mode 100644
index ee6cad3..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_templates/page.html
+++ /dev/null
@@ -1,4 +0,0 @@
-{% extends 'layout.html' %}
-{% block body %}
-  {{ body }}
-{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/_templates/search.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/search.html b/ambari-common/src/main/python/jinja2/docs/_templates/search.html
deleted file mode 100644
index 0c942b7..0000000
--- a/ambari-common/src/main/python/jinja2/docs/_templates/search.html
+++ /dev/null
@@ -1,35 +0,0 @@
-{% extends "layout.html" %}
-{% set title = 'Search' %}
-{% block extrahead %}
-    <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
-{% endblock %}
-{% block body %}
-  <h1 id="search-documentation">Search</h1>
-  <p>
-    From here you can search these documents. Enter your search
-    words into the box below and click "search". Note that the search
-    function will automatically search for all of the words. Pages
-    containing less words won't appear in the result list.
-  </p>
-  <form action="" method="get"><p>
-    <input type="text" name="q" value="">
-    <input type="submit" value="search">
-  </p></form>
-  {% if search_performed %}
-    <h2>Search Results</h2>
-    {% if not search_results %}
-      <p>Your search did not match any results.</p>
-    {% endif %}
-  {% endif %}
-  <div id="search-results">
-  {% if search_results %}
-    <ul>
-    {% for href, caption, context in search_results %}
-      <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
-        <div class="context">{{ context|e }}</div>
-      </li>
-    {% endfor %}
-    </ul>
-  {% endif %}
-  </div>
-{% endblock %}


[59/59] [abbrv] git commit: Merge branch 'trunk' into branch-alerts-dev

Posted by nc...@apache.org.
Merge branch 'trunk' into branch-alerts-dev


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/91ae5f27
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/91ae5f27
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/91ae5f27

Branch: refs/heads/branch-alerts-dev
Commit: 91ae5f27e98ec4d81c7299480b8adb3619e31c5b
Parents: 0de98b0 ad983de
Author: Nate Cole <nc...@hortonworks.com>
Authored: Thu Sep 4 18:35:01 2014 -0400
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Thu Sep 4 18:35:01 2014 -0400

----------------------------------------------------------------------
 .../src/main/resources/ui/admin-web/gulpfile.js |   51 -
 .../main/resources/ui/admin-web/package.json    |    9 -
 ambari-agent/pom.xml                            |   12 +-
 .../src/main/python/ambari_agent/HostInfo.py    |    2 +-
 .../test/python/ambari_agent/TestHardware.py    |    4 +-
 .../resource_management/TestContentSources.py   |    2 +-
 .../resource_management/TestPackageResource.py  |    8 +-
 .../TestRepositoryResource.py                   |   16 +-
 .../src/main/python/ambari_commons/os_check.py  |    8 +-
 .../src/main/python/ambari_jinja2/AUTHORS       |   31 +
 .../src/main/python/ambari_jinja2/CHANGES       |  235 +++
 .../src/main/python/ambari_jinja2/LICENSE       |   31 +
 .../src/main/python/ambari_jinja2/MANIFEST.in   |   12 +
 .../src/main/python/ambari_jinja2/Makefile      |    4 +
 .../ambari_jinja2/ambari_jinja2/__init__.py     |   73 +
 .../ambari_jinja2/ambari_jinja2/_debugsupport.c |   78 +
 .../ambari_jinja2/_markupsafe/__init__.py       |  225 +++
 .../ambari_jinja2/_markupsafe/_bundle.py        |   49 +
 .../ambari_jinja2/_markupsafe/_constants.py     |  267 +++
 .../ambari_jinja2/_markupsafe/_native.py        |   45 +
 .../ambari_jinja2/_markupsafe/tests.py          |   80 +
 .../ambari_jinja2/ambari_jinja2/_stringdefs.py  |  130 ++
 .../ambari_jinja2/ambari_jinja2/bccache.py      |  280 +++
 .../ambari_jinja2/ambari_jinja2/compiler.py     | 1640 ++++++++++++++++++
 .../ambari_jinja2/ambari_jinja2/constants.py    |   32 +
 .../python/ambari_jinja2/ambari_jinja2/debug.py |  308 ++++
 .../ambari_jinja2/ambari_jinja2/defaults.py     |   40 +
 .../ambari_jinja2/ambari_jinja2/environment.py  | 1118 ++++++++++++
 .../ambari_jinja2/ambari_jinja2/exceptions.py   |  143 ++
 .../python/ambari_jinja2/ambari_jinja2/ext.py   |  610 +++++++
 .../ambari_jinja2/ambari_jinja2/filters.py      |  719 ++++++++
 .../python/ambari_jinja2/ambari_jinja2/lexer.py |  681 ++++++++
 .../ambari_jinja2/ambari_jinja2/loaders.py      |  449 +++++
 .../python/ambari_jinja2/ambari_jinja2/meta.py  |  102 ++
 .../python/ambari_jinja2/ambari_jinja2/nodes.py |  901 ++++++++++
 .../ambari_jinja2/ambari_jinja2/optimizer.py    |   68 +
 .../ambari_jinja2/ambari_jinja2/parser.py       |  896 ++++++++++
 .../ambari_jinja2/ambari_jinja2/runtime.py      |  544 ++++++
 .../ambari_jinja2/ambari_jinja2/sandbox.py      |  271 +++
 .../python/ambari_jinja2/ambari_jinja2/tests.py |  146 ++
 .../ambari_jinja2/testsuite/__init__.py         |   95 +
 .../ambari_jinja2/testsuite/api.py              |  240 +++
 .../ambari_jinja2/testsuite/core_tags.py        |  286 +++
 .../ambari_jinja2/testsuite/debug.py            |   60 +
 .../ambari_jinja2/testsuite/doctests.py         |   29 +
 .../ambari_jinja2/testsuite/ext.py              |  455 +++++
 .../ambari_jinja2/testsuite/filters.py          |  291 ++++
 .../ambari_jinja2/testsuite/imports.py          |  144 ++
 .../ambari_jinja2/testsuite/inheritance.py      |  208 +++
 .../ambari_jinja2/testsuite/lexnparse.py        |  390 +++++
 .../ambari_jinja2/testsuite/loader.py           |  191 ++
 .../ambari_jinja2/testsuite/regression.py       |  258 +++
 .../testsuite/res/templates/broken.html         |    3 +
 .../testsuite/res/templates/foo/test.html       |    1 +
 .../testsuite/res/templates/syntaxerror.html    |    4 +
 .../testsuite/res/templates/test.html           |    1 +
 .../ambari_jinja2/testsuite/security.py         |  134 ++
 .../ambari_jinja2/testsuite/tests.py            |   87 +
 .../ambari_jinja2/testsuite/utils.py            |   85 +
 .../python/ambari_jinja2/ambari_jinja2/utils.py |  601 +++++++
 .../ambari_jinja2/ambari_jinja2/visitor.py      |   87 +
 .../python/ambari_jinja2/artwork/jinjalogo.svg  |  132 ++
 .../custom_fixers/fix_alt_unicode.py            |   13 +
 .../custom_fixers/fix_broken_reraising.py       |   21 +
 .../ambari_jinja2/custom_fixers/fix_xrange2.py  |   11 +
 .../src/main/python/ambari_jinja2/docs/Makefile |   75 +
 .../python/ambari_jinja2/docs/_static/jinja.js  |   26 +
 .../python/ambari_jinja2/docs/_static/print.css |    5 +
 .../python/ambari_jinja2/docs/_static/style.css |  390 +++++
 .../ambari_jinja2/docs/_templates/genindex.html |   36 +
 .../ambari_jinja2/docs/_templates/layout.html   |   77 +
 .../docs/_templates/opensearch.xml              |    9 +
 .../ambari_jinja2/docs/_templates/page.html     |    4 +
 .../ambari_jinja2/docs/_templates/search.html   |   35 +
 .../src/main/python/ambari_jinja2/docs/api.rst  |  787 +++++++++
 .../ambari_jinja2/docs/cache_extension.py       |   56 +
 .../python/ambari_jinja2/docs/changelog.rst     |    3 +
 .../src/main/python/ambari_jinja2/docs/conf.py  |  141 ++
 .../python/ambari_jinja2/docs/extensions.rst    |  347 ++++
 .../src/main/python/ambari_jinja2/docs/faq.rst  |  191 ++
 .../main/python/ambari_jinja2/docs/index.rst    |   27 +
 .../python/ambari_jinja2/docs/integration.rst   |   88 +
 .../main/python/ambari_jinja2/docs/intro.rst    |  168 ++
 .../main/python/ambari_jinja2/docs/jinjaext.py  |  192 ++
 .../main/python/ambari_jinja2/docs/sandbox.rst  |   46 +
 .../python/ambari_jinja2/docs/switching.rst     |  242 +++
 .../python/ambari_jinja2/docs/templates.rst     | 1365 +++++++++++++++
 .../main/python/ambari_jinja2/docs/tricks.rst   |  100 ++
 .../ambari_jinja2/examples/basic/cycle.py       |   13 +
 .../ambari_jinja2/examples/basic/debugger.py    |    7 +
 .../ambari_jinja2/examples/basic/inheritance.py |   12 +
 .../examples/basic/templates/broken.html        |    6 +
 .../examples/basic/templates/subbroken.html     |    3 +
 .../python/ambari_jinja2/examples/basic/test.py |   27 +
 .../basic/test_filter_and_linestatements.py     |   25 +
 .../examples/basic/test_loop_filter.py          |   12 +
 .../ambari_jinja2/examples/basic/translate.py   |    6 +
 .../main/python/ambari_jinja2/examples/bench.py |  433 +++++
 .../python/ambari_jinja2/examples/profile.py    |   52 +
 .../examples/rwbench/django/_form.html          |    1 +
 .../examples/rwbench/django/_input_field.html   |    1 +
 .../examples/rwbench/django/_textarea.html      |    1 +
 .../examples/rwbench/django/index.html          |   29 +
 .../examples/rwbench/django/layout.html         |   29 +
 .../ambari_jinja2/examples/rwbench/djangoext.py |  135 ++
 .../examples/rwbench/genshi/helpers.html        |   12 +
 .../examples/rwbench/genshi/index.html          |   41 +
 .../examples/rwbench/genshi/layout.html         |   30 +
 .../examples/rwbench/jinja/helpers.html         |   12 +
 .../examples/rwbench/jinja/index.html           |   29 +
 .../examples/rwbench/jinja/layout.html          |   29 +
 .../examples/rwbench/mako/helpers.html          |   11 +
 .../examples/rwbench/mako/index.html            |   31 +
 .../examples/rwbench/mako/layout.html           |   30 +
 .../ambari_jinja2/examples/rwbench/rwbench.py   |  112 ++
 .../python/ambari_jinja2/ext/Vim/htmljinja.vim  |   27 +
 .../main/python/ambari_jinja2/ext/Vim/jinja.vim |  113 ++
 .../ext/django2jinja/django2jinja.py            |  768 ++++++++
 .../ambari_jinja2/ext/django2jinja/example.py   |    7 +
 .../ext/django2jinja/templates/index.html       |   58 +
 .../ext/django2jinja/templates/layout.html      |    4 +
 .../ext/django2jinja/templates/subtemplate.html |    1 +
 .../python/ambari_jinja2/ext/djangojinja2.py    |   86 +
 .../python/ambari_jinja2/ext/inlinegettext.py   |   78 +
 .../src/main/python/ambari_jinja2/ext/jinja.el  |  213 +++
 .../main/python/ambari_jinja2/jinja2-debug.py   |   40 +
 .../main/python/ambari_jinja2/scripts/pylintrc  |  301 ++++
 .../src/main/python/ambari_jinja2/setup.cfg     |    6 +
 .../src/main/python/ambari_jinja2/setup.py      |  110 ++
 ambari-common/src/main/python/jinja2/AUTHORS    |   31 -
 ambari-common/src/main/python/jinja2/CHANGES    |  235 ---
 ambari-common/src/main/python/jinja2/LICENSE    |   31 -
 .../src/main/python/jinja2/MANIFEST.in          |   12 -
 ambari-common/src/main/python/jinja2/Makefile   |    4 -
 .../main/python/jinja2/artwork/jinjalogo.svg    |  132 --
 .../python/jinja2/custom_fixers/__init__.py     |    0
 .../jinja2/custom_fixers/fix_alt_unicode.py     |   13 -
 .../custom_fixers/fix_broken_reraising.py       |   21 -
 .../python/jinja2/custom_fixers/fix_xrange2.py  |   11 -
 .../src/main/python/jinja2/docs/Makefile        |   75 -
 .../src/main/python/jinja2/docs/_build/.ignore  |    0
 .../src/main/python/jinja2/docs/_static/.ignore |    0
 .../main/python/jinja2/docs/_static/jinja.js    |   26 -
 .../main/python/jinja2/docs/_static/print.css   |    5 -
 .../main/python/jinja2/docs/_static/style.css   |  390 -----
 .../main/python/jinja2/docs/_templates/.ignore  |    0
 .../python/jinja2/docs/_templates/genindex.html |   36 -
 .../python/jinja2/docs/_templates/layout.html   |   77 -
 .../jinja2/docs/_templates/opensearch.xml       |    9 -
 .../python/jinja2/docs/_templates/page.html     |    4 -
 .../python/jinja2/docs/_templates/search.html   |   35 -
 .../src/main/python/jinja2/docs/api.rst         |  787 ---------
 .../main/python/jinja2/docs/cache_extension.py  |   56 -
 .../src/main/python/jinja2/docs/changelog.rst   |    3 -
 .../src/main/python/jinja2/docs/conf.py         |  141 --
 .../src/main/python/jinja2/docs/extensions.rst  |  347 ----
 .../src/main/python/jinja2/docs/faq.rst         |  191 --
 .../src/main/python/jinja2/docs/index.rst       |   27 -
 .../src/main/python/jinja2/docs/integration.rst |   88 -
 .../src/main/python/jinja2/docs/intro.rst       |  168 --
 .../src/main/python/jinja2/docs/jinjaext.py     |  192 --
 .../src/main/python/jinja2/docs/sandbox.rst     |   46 -
 .../src/main/python/jinja2/docs/switching.rst   |  242 ---
 .../src/main/python/jinja2/docs/templates.rst   | 1365 ---------------
 .../src/main/python/jinja2/docs/tricks.rst      |  100 --
 .../main/python/jinja2/examples/basic/cycle.py  |   13 -
 .../python/jinja2/examples/basic/debugger.py    |    7 -
 .../python/jinja2/examples/basic/inheritance.py |   12 -
 .../jinja2/examples/basic/templates/broken.html |    6 -
 .../examples/basic/templates/subbroken.html     |    3 -
 .../main/python/jinja2/examples/basic/test.py   |   27 -
 .../basic/test_filter_and_linestatements.py     |   25 -
 .../jinja2/examples/basic/test_loop_filter.py   |   12 -
 .../python/jinja2/examples/basic/translate.py   |    6 -
 .../src/main/python/jinja2/examples/bench.py    |  433 -----
 .../src/main/python/jinja2/examples/profile.py  |   52 -
 .../jinja2/examples/rwbench/django/_form.html   |    1 -
 .../examples/rwbench/django/_input_field.html   |    1 -
 .../examples/rwbench/django/_textarea.html      |    1 -
 .../jinja2/examples/rwbench/django/index.html   |   29 -
 .../jinja2/examples/rwbench/django/layout.html  |   29 -
 .../python/jinja2/examples/rwbench/djangoext.py |  135 --
 .../jinja2/examples/rwbench/genshi/helpers.html |   12 -
 .../jinja2/examples/rwbench/genshi/index.html   |   41 -
 .../jinja2/examples/rwbench/genshi/layout.html  |   30 -
 .../jinja2/examples/rwbench/jinja/helpers.html  |   12 -
 .../jinja2/examples/rwbench/jinja/index.html    |   29 -
 .../jinja2/examples/rwbench/jinja/layout.html   |   29 -
 .../jinja2/examples/rwbench/mako/helpers.html   |   11 -
 .../jinja2/examples/rwbench/mako/index.html     |   31 -
 .../jinja2/examples/rwbench/mako/layout.html    |   30 -
 .../python/jinja2/examples/rwbench/rwbench.py   |  112 --
 .../main/python/jinja2/ext/Vim/htmljinja.vim    |   27 -
 .../src/main/python/jinja2/ext/Vim/jinja.vim    |  113 --
 .../jinja2/ext/django2jinja/django2jinja.py     |  768 --------
 .../python/jinja2/ext/django2jinja/example.py   |    7 -
 .../ext/django2jinja/templates/index.html       |   58 -
 .../ext/django2jinja/templates/layout.html      |    4 -
 .../ext/django2jinja/templates/subtemplate.html |    1 -
 .../src/main/python/jinja2/ext/djangojinja2.py  |   86 -
 .../src/main/python/jinja2/ext/inlinegettext.py |   78 -
 .../src/main/python/jinja2/ext/jinja.el         |  213 ---
 .../src/main/python/jinja2/jinja2-debug.py      |   40 -
 .../src/main/python/jinja2/jinja2/__init__.py   |   73 -
 .../main/python/jinja2/jinja2/_debugsupport.c   |   78 -
 .../jinja2/jinja2/_markupsafe/__init__.py       |  225 ---
 .../python/jinja2/jinja2/_markupsafe/_bundle.py |   49 -
 .../jinja2/jinja2/_markupsafe/_constants.py     |  267 ---
 .../python/jinja2/jinja2/_markupsafe/_native.py |   45 -
 .../python/jinja2/jinja2/_markupsafe/tests.py   |   80 -
 .../main/python/jinja2/jinja2/_stringdefs.py    |  130 --
 .../src/main/python/jinja2/jinja2/bccache.py    |  280 ---
 .../src/main/python/jinja2/jinja2/compiler.py   | 1640 ------------------
 .../src/main/python/jinja2/jinja2/constants.py  |   32 -
 .../src/main/python/jinja2/jinja2/debug.py      |  308 ----
 .../src/main/python/jinja2/jinja2/defaults.py   |   40 -
 .../main/python/jinja2/jinja2/environment.py    | 1118 ------------
 .../src/main/python/jinja2/jinja2/exceptions.py |  143 --
 .../src/main/python/jinja2/jinja2/ext.py        |  610 -------
 .../src/main/python/jinja2/jinja2/filters.py    |  719 --------
 .../src/main/python/jinja2/jinja2/lexer.py      |  681 --------
 .../src/main/python/jinja2/jinja2/loaders.py    |  449 -----
 .../src/main/python/jinja2/jinja2/meta.py       |  102 --
 .../src/main/python/jinja2/jinja2/nodes.py      |  901 ----------
 .../src/main/python/jinja2/jinja2/optimizer.py  |   68 -
 .../src/main/python/jinja2/jinja2/parser.py     |  896 ----------
 .../src/main/python/jinja2/jinja2/runtime.py    |  544 ------
 .../src/main/python/jinja2/jinja2/sandbox.py    |  271 ---
 .../src/main/python/jinja2/jinja2/tests.py      |  146 --
 .../python/jinja2/jinja2/testsuite/__init__.py  |   95 -
 .../main/python/jinja2/jinja2/testsuite/api.py  |  240 ---
 .../python/jinja2/jinja2/testsuite/core_tags.py |  286 ---
 .../python/jinja2/jinja2/testsuite/debug.py     |   60 -
 .../python/jinja2/jinja2/testsuite/doctests.py  |   29 -
 .../main/python/jinja2/jinja2/testsuite/ext.py  |  455 -----
 .../python/jinja2/jinja2/testsuite/filters.py   |  291 ----
 .../python/jinja2/jinja2/testsuite/imports.py   |  144 --
 .../jinja2/jinja2/testsuite/inheritance.py      |  208 ---
 .../python/jinja2/jinja2/testsuite/lexnparse.py |  390 -----
 .../python/jinja2/jinja2/testsuite/loader.py    |  191 --
 .../jinja2/jinja2/testsuite/regression.py       |  258 ---
 .../jinja2/jinja2/testsuite/res/__init__.py     |    0
 .../jinja2/testsuite/res/templates/broken.html  |    3 -
 .../testsuite/res/templates/foo/test.html       |    1 -
 .../testsuite/res/templates/syntaxerror.html    |    4 -
 .../jinja2/testsuite/res/templates/test.html    |    1 -
 .../python/jinja2/jinja2/testsuite/security.py  |  134 --
 .../python/jinja2/jinja2/testsuite/tests.py     |   87 -
 .../python/jinja2/jinja2/testsuite/utils.py     |   85 -
 .../src/main/python/jinja2/jinja2/utils.py      |  601 -------
 .../src/main/python/jinja2/jinja2/visitor.py    |   87 -
 .../src/main/python/jinja2/scripts/pylintrc     |  301 ----
 ambari-common/src/main/python/jinja2/setup.cfg  |    6 -
 ambari-common/src/main/python/jinja2/setup.py   |  110 --
 .../core/providers/__init__.py                  |    2 +-
 .../python/resource_management/core/source.py   |    2 +-
 .../python/resource_management/core/system.py   |    4 +-
 .../libraries/providers/__init__.py             |    4 +-
 .../libraries/providers/monitor_webserver.py    |    2 +-
 .../libraries/providers/repository.py           |    2 +-
 ambari-server/pom.xml                           |    4 +-
 .../server/api/services/AmbariMetaInfo.java     |    2 +-
 .../server/configuration/Configuration.java     |    8 +-
 .../apache/ambari/server/orm/dao/GroupDAO.java  |    1 +
 .../apache/ambari/server/orm/dao/UserDAO.java   |    1 +
 .../authorization/AmbariLdapDataPopulator.java  |    5 +-
 .../org/apache/ambari/server/state/Host.java    |    2 +-
 .../server/state/stack/LatestRepoCallable.java  |    2 +-
 .../ambari/server/state/stack/OsFamily.java     |    6 +-
 .../server/upgrade/UpgradeCatalog161.java       |   22 +
 ambari-server/src/main/python/ambari-server.py  |    2 +
 .../src/main/python/ambari_server/utils.py      |   12 +-
 ambari-server/src/main/python/bootstrap.py      |   14 +-
 ambari-server/src/main/python/setupAgent.py     |    8 +-
 ambari-server/src/main/resources/os_family.json |    2 +-
 .../main/resources/scripts/kerberos-setup.sh    |    4 +-
 .../src/main/resources/scripts/stack_advisor.py |   19 +-
 .../scripts/repo_initialization.py              |    2 +-
 .../before-INSTALL/templates/repo_debian.j2     |    1 -
 .../before-INSTALL/templates/repo_ubuntu.j2     |    1 +
 .../HBASE/package/scripts/hbase_decommission.py |   62 +-
 .../services/HBASE/package/scripts/params.py    |    1 +
 .../stacks/HDP/1.3.2/services/stack_advisor.py  |  377 +---
 .../stacks/HDP/1.3.3/services/stack_advisor.py  |    4 -
 .../stacks/HDP/1.3/services/stack_advisor.py    |    4 -
 .../scripts/repo_initialization.py              |    2 +-
 .../before-INSTALL/templates/repo_debian.j2     |    1 -
 .../before-INSTALL/templates/repo_ubuntu.j2     |    1 +
 .../HDP/2.0.6/services/GANGLIA/metainfo.xml     |    2 +-
 .../GANGLIA/package/scripts/functions.py        |    4 +-
 .../GANGLIA/package/scripts/ganglia_server.py   |    2 +-
 .../services/GANGLIA/package/scripts/params.py  |    4 +-
 .../HBASE/package/scripts/hbase_decommission.py |   62 +-
 .../services/HBASE/package/scripts/params.py    |    1 +
 .../stacks/HDP/2.0.6/services/HDFS/metainfo.xml |    2 +-
 .../stacks/HDP/2.0.6/services/HIVE/metainfo.xml |    2 +-
 .../services/HIVE/package/scripts/params.py     |    2 +-
 .../HIVE/package/scripts/status_params.py       |    2 +-
 .../HDP/2.0.6/services/NAGIOS/metainfo.xml      |    2 +-
 .../services/NAGIOS/package/scripts/nagios.py   |    8 +-
 .../services/NAGIOS/package/scripts/params.py   |   10 +-
 .../NAGIOS/package/templates/nagios.conf.j2     |    2 +-
 .../HDP/2.0.6/services/OOZIE/metainfo.xml       |    2 +-
 .../services/OOZIE/package/files/oozieSmoke2.sh |    2 +-
 .../stacks/HDP/2.0.6/services/stack_advisor.py  |  316 +---
 .../2.1.GlusterFS/services/FLUME/metainfo.xml   |   31 +
 .../2.1.GlusterFS/services/HBASE/metainfo.xml   |    5 +
 .../2.1.GlusterFS/services/OOZIE/metainfo.xml   |    4 +-
 .../2.1.GlusterFS/services/SQOOP/metainfo.xml   |    3 +
 .../2.1.GlusterFS/services/YARN/metainfo.xml    |   10 +-
 .../resources/stacks/HDP/2.1/repos/repoinfo.xml |    2 +-
 .../stacks/HDP/2.1/services/OOZIE/metainfo.xml  |    2 +-
 .../stacks/HDP/2.1/services/SQOOP/metainfo.xml  |    4 -
 .../stacks/HDP/2.1/services/stack_advisor.py    |   64 +-
 .../resources/stacks/HDP/2.2.1/metainfo.xml     |   23 +
 .../stacks/HDP/2.2.1/repos/repoinfo.xml         |   67 +
 .../stacks/HDP/2.2.1/role_command_order.json    |   85 +
 .../HDP/2.2.1/services/FALCON/metainfo.xml      |   26 +
 .../HDP/2.2.1/services/FLUME/metainfo.xml       |   26 +
 .../HDP/2.2.1/services/HBASE/metainfo.xml       |   26 +
 .../stacks/HDP/2.2.1/services/HDFS/metainfo.xml |   27 +
 .../stacks/HDP/2.2.1/services/HIVE/metainfo.xml |   31 +
 .../HDP/2.2.1/services/OOZIE/metainfo.xml       |   26 +
 .../stacks/HDP/2.2.1/services/PIG/metainfo.xml  |   26 +
 .../HDP/2.2.1/services/SQOOP/metainfo.xml       |   26 +
 .../HDP/2.2.1/services/STORM/metainfo.xml       |   27 +
 .../stacks/HDP/2.2.1/services/TEZ/metainfo.xml  |   26 +
 .../HDP/2.2.1/services/WEBHCAT/metainfo.xml     |   26 +
 .../stacks/HDP/2.2.1/services/YARN/metainfo.xml |   31 +
 .../HDP/2.2.1/services/ZOOKEEPER/metainfo.xml   |   26 +
 .../src/main/resources/stacks/stack_advisor.py  |  271 +++
 .../server/api/services/AmbariMetaInfoTest.java |    1 -
 .../AmbariManagementControllerTest.java         |    4 +-
 .../AmbariLdapDataPopulatorTest.java            |   22 +-
 .../server/upgrade/UpgradeCatalog161Test.java   |   24 +
 .../src/test/python/TestAmbariServer.py         |   11 +-
 ambari-server/src/test/python/TestBootstrap.py  |    6 +-
 ambari-server/src/test/python/TestOSCheck.py    |   12 +-
 ambari-server/src/test/python/TestSetupAgent.py |   64 +-
 .../src/test/python/TestStackAdvisor.py         |  323 +++-
 ambari-server/src/test/python/TestUtils.py      |    6 +-
 .../stacks/1.3.2/HBASE/test_hbase_master.py     |    6 +-
 .../python/stacks/1.3.2/configs/default.json    |    4 +-
 .../hooks/before-INSTALL/test_before_install.py |   83 +-
 .../stacks/2.0.6/HBASE/test_hbase_master.py     |    6 +-
 .../stacks/2.0.6/common/test_stack_advisor.py   |    6 +-
 .../python/stacks/2.0.6/configs/default.json    |    5 +-
 .../hooks/before-INSTALL/test_before_install.py |   98 +-
 ambari-server/src/test/python/unitTests.py      |    2 +-
 .../HDP/2.0.1/services/GANGLIA/metainfo.xml     |    2 +-
 .../stacks/HDP/2.0.1/services/HDFS/metainfo.xml |    2 +-
 .../stacks/HDP/2.0.1/services/HIVE/metainfo.xml |    2 +-
 .../HDP/2.0.1/services/OOZIE/metainfo.xml       |    2 +-
 .../HDP/2.0.5/services/GANGLIA/metainfo.xml     |    2 +-
 .../stacks/HDP/2.0.5/services/HDFS/metainfo.xml |    2 +-
 .../stacks/HDP/2.0.5/services/HIVE/metainfo.xml |    2 +-
 .../HDP/2.0.5/services/OOZIE/metainfo.xml       |    2 +-
 .../stacks/HDP/2.0.7/services/HIVE/metainfo.xml |    2 +-
 .../assets/data/wizard/stack/HDP_versions.json  |   10 +-
 ambari-web/app/assets/test/tests.js             |    1 +
 ambari-web/app/controllers/application.js       |    4 +
 .../controllers/global/cluster_controller.js    |    6 +-
 ambari-web/app/controllers/installer.js         |    2 +-
 .../app/controllers/main/admin/repositories.js  |    2 +-
 .../main/admin/security/add/step4.js            |    3 +
 .../security/security_progress_controller.js    |    6 +-
 ambari-web/app/controllers/main/host/details.js |   11 +-
 .../controllers/main/service/info/configs.js    |   56 +-
 .../app/controllers/wizard/step3_controller.js  |    2 +-
 .../app/controllers/wizard/step7_controller.js  |    8 +
 .../app/controllers/wizard/step8_controller.js  |    2 +-
 .../mappers/service_config_version_mapper.js    |    1 +
 ambari-web/app/messages.js                      |    1 +
 ambari-web/app/models/service_config.js         |    8 +-
 ambari-web/app/models/service_config_version.js |    9 +-
 ambari-web/app/router.js                        |    2 +-
 ambari-web/app/routes/main.js                   |   19 +-
 ambari-web/app/styles/application.less          |   40 +-
 ambari-web/app/templates/application.hbs        |   22 +-
 .../common/configs/config_history_flow.hbs      |   16 +-
 .../templates/main/dashboard/config_history.hbs |    4 +-
 ambari-web/app/utils/blueprint.js               |    6 +-
 .../views/common/configs/config_history_flow.js |   42 +-
 .../app/views/common/configs/services_config.js |    2 +-
 .../app/views/common/filter_combo_cleanable.js  |    1 +
 ambari-web/app/views/main/menu.js               |   37 +-
 ambari-web/app/views/main/service/menu.js       |    2 +-
 .../views/common/filter_combo_cleanable_test.js |   42 +
 ambari-web/vendor/scripts/jquery.timeago.js     |    6 +-
 .../jobs/src/main/resources/ui/Gruntfile.js     |   13 -
 .../jobs/src/main/resources/ui/package.json     |    1 -
 pom.xml                                         |    2 +
 392 files changed, 23368 insertions(+), 22538 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/91ae5f27/ambari-agent/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/91ae5f27/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/91ae5f27/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/91ae5f27/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------


[24/59] [abbrv] git commit: AMBARI-7068. BE: HDP 2.0.6 stack_advisor.py should be tolerant of services not owned by it

Posted by nc...@apache.org.
AMBARI-7068. BE: HDP 2.0.6 stack_advisor.py should be tolerant of services not owned by it


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/dc269bb1
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/dc269bb1
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/dc269bb1

Branch: refs/heads/branch-alerts-dev
Commit: dc269bb1588bee0bf6619f8a70ad1f144591ca09
Parents: 24dea68
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Wed Sep 3 14:28:25 2014 -0700
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Wed Sep 3 16:16:20 2014 -0700

----------------------------------------------------------------------
 .../src/main/resources/scripts/stack_advisor.py |  19 +-
 .../stacks/HDP/1.3.2/services/stack_advisor.py  | 377 +++++--------------
 .../stacks/HDP/1.3.3/services/stack_advisor.py  |   4 -
 .../stacks/HDP/1.3/services/stack_advisor.py    |   4 -
 .../stacks/HDP/2.0.6/services/stack_advisor.py  | 308 +++------------
 .../stacks/HDP/2.1/services/stack_advisor.py    |  64 ++--
 .../src/main/resources/stacks/stack_advisor.py  | 271 +++++++++++++
 .../src/test/python/TestStackAdvisor.py         | 323 ++++++++++++++--
 .../stacks/2.0.6/common/test_stack_advisor.py   |   2 +-
 9 files changed, 738 insertions(+), 634 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/scripts/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/scripts/stack_advisor.py b/ambari-server/src/main/resources/scripts/stack_advisor.py
index ed50866..566fe7f 100755
--- a/ambari-server/src/main/resources/scripts/stack_advisor.py
+++ b/ambari-server/src/main/resources/scripts/stack_advisor.py
@@ -34,6 +34,7 @@ USAGE = "Usage: <action> <hosts_file> <services_file>\nPossible actions are: {0}
 
 SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
 STACK_ADVISOR_PATH_TEMPLATE = os.path.join(SCRIPT_DIRECTORY, '../stacks/stack_advisor.py')
+STACK_ADVISOR_DEFAULT_IMPL_CLASS = 'DefaultStackAdvisor'
 STACK_ADVISOR_IMPL_PATH_TEMPLATE = os.path.join(SCRIPT_DIRECTORY, './../stacks/{0}/{1}/services/stack_advisor.py')
 STACK_ADVISOR_IMPL_CLASS_TEMPLATE = '{0}{1}StackAdvisor'
 
@@ -113,9 +114,10 @@ def instantiateStackAdvisor(stackName, stackVersion, parentVersions):
   """Instantiates StackAdvisor implementation for the specified Stack"""
   import imp
 
-  stackAdvisorPath = STACK_ADVISOR_PATH_TEMPLATE.format(stackName)
-  with open(stackAdvisorPath, 'rb') as fp:
-    stack_advisor = imp.load_module( 'stack_advisor', fp, stackAdvisorPath, ('.py', 'rb', imp.PY_SOURCE) )
+  with open(STACK_ADVISOR_PATH_TEMPLATE, 'rb') as fp:
+    default_stack_advisor = imp.load_module('stack_advisor', fp, STACK_ADVISOR_PATH_TEMPLATE, ('.py', 'rb', imp.PY_SOURCE))
+  className = STACK_ADVISOR_DEFAULT_IMPL_CLASS
+  stack_advisor = default_stack_advisor
 
   versions = [stackVersion]
   versions.extend(parentVersions)
@@ -123,20 +125,21 @@ def instantiateStackAdvisor(stackName, stackVersion, parentVersions):
   for version in reversed(versions):
     try:
       path = STACK_ADVISOR_IMPL_PATH_TEMPLATE.format(stackName, version)
-      className = STACK_ADVISOR_IMPL_CLASS_TEMPLATE.format(stackName, version.replace('.', ''))
 
       with open(path, 'rb') as fp:
-        stack_advisor_impl = imp.load_module('stack_advisor_impl', fp, path, ('.py', 'rb', imp.PY_SOURCE))
+        stack_advisor = imp.load_module('stack_advisor_impl', fp, path, ('.py', 'rb', imp.PY_SOURCE))
+      className = STACK_ADVISOR_IMPL_CLASS_TEMPLATE.format(stackName, version.replace('.', ''))
       print "StackAdvisor implementation for stack {0}, version {1} was loaded".format(stackName, version)
-    except Exception, e:
+    except Exception:
       print "StackAdvisor implementation for stack {0}, version {1} was not found".format(stackName, version)
 
   try:
-    clazz = getattr(stack_advisor_impl, className)
+    clazz = getattr(stack_advisor, className)
+    print "Returning " + className + " implementation"
     return clazz()
   except Exception, e:
     print "Returning default implementation"
-    return stack_advisor.StackAdvisor()
+    return default_stack_advisor.DefaultStackAdvisor()
 
 
 if __name__ == '__main__':

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py
index 17a26e2..c9b119f 100644
--- a/ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py
@@ -18,169 +18,19 @@ limitations under the License.
 """
 
 import re
-import socket
 import sys
 
-from stack_advisor import StackAdvisor
+from stack_advisor import DefaultStackAdvisor
 
-class HDP132StackAdvisor(StackAdvisor):
+class HDP132StackAdvisor(DefaultStackAdvisor):
 
-  def recommendComponentLayout(self, services, hosts):
-    """
-    Returns Services object with hostnames array populated for components
-    If hostnames are populated for some components (partial blueprint) - these components will not be processed
-    """
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
-    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
-
-    recommendations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "hosts": hostsList,
-      "services": servicesList,
-      "recommendations": {
-        "blueprint": {
-          "host_groups": [ ]
-        },
-        "blueprint_cluster_binding": {
-          "host_groups": [ ]
-        }
-      }
-    }
-
-    hostsComponentsMap = {}
-
-    #extend 'hostsComponentsMap' with MASTER components
-    for service in services["services"]:
-      masterComponents = [component for component in service["components"] if isMaster(component)]
-      for component in masterComponents:
-        componentName = component["StackServiceComponents"]["component_name"]
-        hostsForComponent = []
-
-        if isAlreadyPopulated(component):
-          hostsForComponent = component["StackServiceComponents"]["hostnames"]
-        else:
-          availableHosts = hostsList
-          if len(hostsList) > 1 and self.isNotPreferableOnAmbariServerHost(component):
-            availableHosts = [hostName for hostName in hostsList if not isLocalHost(hostName)]
-
-          if isMasterWithMultipleInstances(component):
-            hostsCount = defaultNoOfMasterHosts(component)
-            if hostsCount > 1: # get first 'hostsCount' available hosts
-              if len(availableHosts) < hostsCount:
-                hostsCount = len(availableHosts)
-              hostsForComponent = availableHosts[:hostsCount]
-            else:
-              hostsForComponent = [self.getHostForComponent(component, availableHosts)]
-          else:
-            hostsForComponent = [self.getHostForComponent(component, availableHosts)]
-
-        #extend 'hostsComponentsMap' with 'hostsForComponent'
-        for hostName in hostsForComponent:
-          if hostName not in hostsComponentsMap:
-            hostsComponentsMap[hostName] = []
-          hostsComponentsMap[hostName].append( { "name":componentName } )
-
-    #extend 'hostsComponentsMap' with Slave and Client Components
-    componentsListList = [service["components"] for service in services["services"]]
-    componentsList = [item for sublist in componentsListList for item in sublist]
-    usedHostsListList = [component["StackServiceComponents"]["hostnames"] for component in componentsList if not self.isNotValuable(component)]
-    utilizedHosts = [item for sublist in usedHostsListList for item in sublist]
-    freeHosts = [hostName for hostName in hostsList if hostName not in utilizedHosts]
-
-    for service in services["services"]:
-      slaveClientComponents = [component for component in service["components"] if isSlave(component) or isClient(component)]
-      for component in slaveClientComponents:
-        componentName = component["StackServiceComponents"]["component_name"]
-        hostsForComponent = []
-
-        if isAlreadyPopulated(component):
-          hostsForComponent = component["StackServiceComponents"]["hostnames"]
-        elif component["StackServiceComponents"]["cardinality"] == "ALL":
-          hostsForComponent = hostsList
-        else:
-          if len(freeHosts) == 0:
-            hostsForComponent = hostsList[-1:]
-          else: # len(freeHosts) >= 1
-            hostsForComponent = freeHosts
-            if isClient(component):
-              hostsForComponent = freeHosts[0:1]
-
-        #extend 'hostsComponentsMap' with 'hostsForComponent'
-        for hostName in hostsForComponent:
-          if hostName not in hostsComponentsMap:
-            hostsComponentsMap[hostName] = []
-          hostsComponentsMap[hostName].append( { "name": componentName } )
-
-    #prepare 'host-group's from 'hostsComponentsMap'
-    host_groups = recommendations["recommendations"]["blueprint"]["host_groups"]
-    bindings = recommendations["recommendations"]["blueprint_cluster_binding"]["host_groups"]
-    index = 0
-    for key in hostsComponentsMap.keys():
-      index += 1
-      host_group_name = "host-group-{0}".format(index)
-      host_groups.append( { "name": host_group_name, "components": hostsComponentsMap[key] } )
-      bindings.append( { "name": host_group_name, "hosts": [{ "fqdn": socket.getfqdn(key) }] } )
-
-    return recommendations
-  pass
-
-  def getHostForComponent(self, component, hostsList):
-    componentName = component["StackServiceComponents"]["component_name"]
-    scheme = self.defineSelectionScheme(componentName)
-
-    if len(hostsList) == 1:
-      return hostsList[0]
-    else:
-      for key in scheme.keys():
-        if isinstance(key, ( int, long )):
-          if len(hostsList) < key:
-            return hostsList[scheme[key]]
-      return hostsList[scheme['else']]
-
-  def defineSelectionScheme(self, componentName):
-    scheme = self.selectionScheme(componentName)
-    if scheme is None:
-      scheme = {"else": 0}
-    return scheme
-
-  def selectionScheme(self, componentName):
-    return {
-      'NAMENODE': {"else": 0},
-      'SECONDARY_NAMENODE': {"else": 1},
-      'HBASE_MASTER': {6: 0, 31: 2, "else": 3},
-
-      'HISTORYSERVER': {31: 1, "else": 2},
-      'RESOURCEMANAGER': {31: 1, "else": 2},
-
-      'OOZIE_SERVER': {6: 1, 31: 2, "else": 3},
-
-      'HIVE_SERVER': {6: 1, 31: 2, "else": 4},
-      'HIVE_METASTORE': {6: 1, 31: 2, "else": 4},
-      'WEBHCAT_SERVER': {6: 1, 31: 2, "else": 4},
-      }.get(componentName, None)
-
-  def isNotPreferableOnAmbariServerHost(self, component):
-    componentName = component["StackServiceComponents"]["component_name"]
-    service = ['GANGLIA_SERVER', 'NAGIOS_SERVER']
-    return componentName in service
-
-  def validateComponentLayout(self, services, hosts):
+  def getLayoutValidationItems(self, services, hosts):
     """Returns array of Validation objects about issues with hostnames components assigned to"""
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-
-    validations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "items": [ ]
-    }
-    items = validations["items"]
+    items = []
 
     # Validating NAMENODE and SECONDARY_NAMENODE are on different hosts if possible
     hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
     hostsCount = len(hostsList)
-    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
 
     componentsListList = [service["components"] for service in services["services"]]
     componentsList = [item for sublist in componentsListList for item in sublist]
@@ -198,32 +48,28 @@ class HDP132StackAdvisor(StackAdvisor):
     # Validating cardinality
     for component in componentsList:
       if component["StackServiceComponents"]["cardinality"] is not None:
-         componentName = component["StackServiceComponents"]["component_name"]
-         componentHostsCount = 0
-         if component["StackServiceComponents"]["hostnames"] is not None:
-           componentHostsCount = len(component["StackServiceComponents"]["hostnames"])
-         cardinality = str(component["StackServiceComponents"]["cardinality"])
-         # cardinality types: null, 1+, 1-2, 1, ALL
-         hostsMax = -sys.maxint - 1
-         hostsMin = sys.maxint
-         hostsMin = 0
-         hostsMax = 0
-         if "+" in cardinality:
-           hostsMin = int(cardinality[:-1])
-           hostsMax = sys.maxint
-         elif "-" in cardinality:
-           nums = cardinality.split("-")
-           hostsMin = int(nums[0])
-           hostsMax = int(nums[1])
-         elif "ALL" == cardinality:
-           hostsMin = hostsCount
-           hostsMax = hostsCount
-         else:
-           hostsMin = int(cardinality)
-           hostsMax = int(cardinality)
-
-         if componentHostsCount > hostsMax or componentHostsCount < hostsMin:
-           items.append( { "type": 'host-component', "level": 'ERROR', "message": 'Cardinality violation, cardinality={0}, hosts count={1}'.format(cardinality, str(componentHostsCount)), "component-name": str(componentName) } )
+        componentName = component["StackServiceComponents"]["component_name"]
+        componentHostsCount = 0
+        if component["StackServiceComponents"]["hostnames"] is not None:
+          componentHostsCount = len(component["StackServiceComponents"]["hostnames"])
+        cardinality = str(component["StackServiceComponents"]["cardinality"])
+        # cardinality types: null, 1+, 1-2, 1, ALL
+        if "+" in cardinality:
+          hostsMin = int(cardinality[:-1])
+          hostsMax = sys.maxint
+        elif "-" in cardinality:
+          nums = cardinality.split("-")
+          hostsMin = int(nums[0])
+          hostsMax = int(nums[1])
+        elif "ALL" == cardinality:
+          hostsMin = hostsCount
+          hostsMax = hostsCount
+        else:
+          hostsMin = int(cardinality)
+          hostsMax = int(cardinality)
+
+        if componentHostsCount > hostsMax or componentHostsCount < hostsMin:
+          items.append( { "type": 'host-component', "level": 'ERROR', "message": 'Cardinality violation, cardinality={0}, hosts count={1}'.format(cardinality, str(componentHostsCount)), "component-name": str(componentName) } )
 
     # Validating host-usage
     usedHostsListList = [component["StackServiceComponents"]["hostnames"] for component in componentsList if not self.isNotValuable(component)]
@@ -232,52 +78,11 @@ class HDP132StackAdvisor(StackAdvisor):
     for host in nonUsedHostsList:
       items.append( { "type": 'host-component', "level": 'ERROR', "message": 'Host is not used', "host": str(host) } )
 
-    return validations
-  pass
-
-  def isNotValuable(self, component):
-    componentName = component["StackServiceComponents"]["component_name"]
-    service = ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR']
-    return componentName in service
-
-  def recommendConfigurations(self, services, hosts):
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
-    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
-    components = [component["StackServiceComponents"]["component_name"]
-                  for service in services["services"]
-                  for component in service["components"]]
-
-    clusterData = self.getClusterData(servicesList, hosts, components)
-
-    recommendations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "hosts": hostsList,
-      "services": servicesList,
-      "recommendations": {
-        "blueprint": {
-          "configurations": {},
-          "host_groups": []
-        },
-        "blueprint_cluster_binding": {
-          "host_groups": []
-        }
-      }
-    }
+    return items
 
-    configurations = recommendations["recommendations"]["blueprint"]["configurations"]
-
-    for service in servicesList:
-      calculation = self.recommendServiceConfigurations(service)
-      if calculation is not None:
-        calculation(configurations, clusterData)
-
-    return recommendations
-
-  def recommendServiceConfigurations(self, service):
+  def getServiceConfiguratorDict(self):
     return {
-    }.get(service, None)
+    }
 
   def putProperty(self, config, configType):
     config[configType] = {"properties": {}}
@@ -361,17 +166,9 @@ class HDP132StackAdvisor(StackAdvisor):
 
     return cluster
 
-
-  def validateConfigurations(self, services, hosts):
+  def getConfigurationsValidationItems(self, services, hosts):
     """Returns array of Validation objects about issues with configuration values provided in services"""
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-
-    validations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "items": [ ]
-    }
-    items = validations["items"]
+    items = []
 
     recommendations = self.recommendConfigurations(services, hosts)
     recommendedDefaults = recommendations["recommendations"]["blueprint"]["configurations"]
@@ -388,50 +185,88 @@ class HDP132StackAdvisor(StackAdvisor):
           if siteProperties is not None:
             resultItems = method(siteProperties, recommendedDefaults[siteName]["properties"])
             items.extend(resultItems)
-    return validations
-    pass
+    return items
+
+  def getServiceConfigurationValidators(self):
+    return {}
 
   def validateServiceConfigurations(self, serviceName):
-    return {
-    }.get(serviceName, None)
+    return self.getServiceConfigurationValidators().get(serviceName, None)
 
-  def toConfigurationValidationErrors(self, items, siteName):
+  def toConfigurationValidationProblems(self, validationProblems, siteName):
     result = []
-    for item in items:
-      if item["message"] is not None:
-        error = { "type": 'configuration', "level": 'ERROR', "message": item["message"], "config-type": siteName, "config-name": item["config-name"] }
-        result.append(error)
+    for validationProblem in validationProblems:
+      validationItem = validationProblem.get("item", None)
+      if validationItem is not None:
+        problem = {"type": 'configuration', "level": validationItem["level"], "message": validationItem["message"],
+                   "config-type": siteName, "config-name": validationProblem["config-name"] }
+        result.append(problem)
     return result
 
+  def getWarnItem(self, message):
+    return {"level": "WARN", "message": message}
+
+  def getErrorItem(self, message):
+    return {"level": "ERROR", "message": message}
+
   def validatorLessThenDefaultValue(self, properties, recommendedDefaults, propertyName):
     if not propertyName in properties:
-      return "Value should be set"
+      return self.getErrorItem("Value should be set")
     value = to_number(properties[propertyName])
     if value is None:
-      return "Value should be integer"
+      return self.getErrorItem("Value should be integer")
     defaultValue = to_number(recommendedDefaults[propertyName])
     if defaultValue is None:
       return None
     if value < defaultValue:
-      return "Value is less than the recommended default of {0}".format(defaultValue)
+      return self.getWarnItem("Value is less than the recommended default of {0}".format(defaultValue))
     return None
 
   def validateXmxValue(self, properties, recommendedDefaults, propertyName):
     if not propertyName in properties:
-      return "Value should be set"
+      return self.getErrorItem("Value should be set")
     value = properties[propertyName]
     defaultValue = recommendedDefaults[propertyName]
     if defaultValue is None:
-      return "Config's default value can't be null or undefined"
+      return self.getErrorItem("Config's default value can't be null or undefined")
     if not checkXmxValueFormat(value):
-      return 'Invalid value format'
+      return self.getErrorItem('Invalid value format')
     valueInt = formatXmxSizeToBytes(getXmxSize(value))
     defaultValueXmx = getXmxSize(defaultValue)
     defaultValueInt = formatXmxSizeToBytes(defaultValueXmx)
     if valueInt < defaultValueInt:
-      return "Value is less than the recommended default of -Xmx" + defaultValueXmx
+      return self.getWarnItem("Value is less than the recommended default of -Xmx" + defaultValueXmx)
     return None
+  def getMastersWithMultipleInstances(self):
+    return ['ZOOKEEPER_SERVER', 'HBASE_MASTER']
 
+  def getNotValuableComponents(self):
+    return ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR']
+
+  def getNotPreferableOnServerComponents(self):
+    return ['GANGLIA_SERVER', 'NAGIOS_SERVER']
+
+  def getCardinalitiesDict(self):
+    return {
+      'ZOOKEEPER_SERVER': {"min": 3},
+      'HBASE_MASTER': {"min": 1},
+      }
+
+  def selectionSchemes(self):
+    return {
+      'NAMENODE': {"else": 0},
+      'SECONDARY_NAMENODE': {"else": 1},
+      'HBASE_MASTER': {6: 0, 31: 2, "else": 3},
+
+      'HISTORYSERVER': {31: 1, "else": 2},
+      'RESOURCEMANAGER': {31: 1, "else": 2},
+
+      'OOZIE_SERVER': {6: 1, 31: 2, "else": 3},
+
+      'HIVE_SERVER': {6: 1, 31: 2, "else": 4},
+      'HIVE_METASTORE': {6: 1, 31: 2, "else": 4},
+      'WEBHCAT_SERVER': {6: 1, 31: 2, "else": 4},
+      }
 
 # Validation helper methods
 def getSiteProperties(configurations, siteName):
@@ -474,46 +309,6 @@ def formatXmxSizeToBytes(value):
     modifier == 'g': 1024 * 1024 * 1024,
     modifier == 't': 1024 * 1024 * 1024 * 1024,
     modifier == 'p': 1024 * 1024 * 1024 * 1024 * 1024
-    }[1]
+  }[1]
   return to_number(value) * m
 
-
-# Recommendation helper methods
-def isAlreadyPopulated(component):
-  if component["StackServiceComponents"]["hostnames"] is not None:
-    return len(component["StackServiceComponents"]["hostnames"]) > 0
-  return False
-
-def isClient(component):
-  return component["StackServiceComponents"]["component_category"] == 'CLIENT'
-
-def isSlave(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  isSlave = component["StackServiceComponents"]["component_category"] == 'SLAVE'
-  return isSlave
-
-def isMaster(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  isMaster = component["StackServiceComponents"]["is_master"]
-  return isMaster
-
-def isLocalHost(hostName):
-  return socket.getfqdn(hostName) == socket.getfqdn()
-
-def isMasterWithMultipleInstances(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  masters = ['ZOOKEEPER_SERVER', 'HBASE_MASTER']
-  return componentName in masters
-
-def defaultNoOfMasterHosts(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  return cardinality(componentName)[min]
-
-
-# Helper dictionaries
-def cardinality(componentName):
-  return {
-    'ZOOKEEPER_SERVER': {min: 3},
-    'HBASE_MASTER': {min: 1},
-    }.get(componentName, {min:1, max:1})
-

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py
index f91efd8..40fac9c 100644
--- a/ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py
@@ -17,9 +17,5 @@ See the License for the specific language governing permissions and
 limitations under the License.
 """
 
-import socket
-
-from stack_advisor import StackAdvisor
-
 class HDP133StackAdvisor(HDP132StackAdvisor):
   pass
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py
index 998ecaa..9360646 100644
--- a/ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py
@@ -17,9 +17,5 @@ See the License for the specific language governing permissions and
 limitations under the License.
 """
 
-import socket
-
-from stack_advisor import StackAdvisor
-
 class HDP13StackAdvisor(HDP133StackAdvisor):
   pass
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
index 4eb8f02..dd4fae3 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
@@ -18,169 +18,19 @@ limitations under the License.
 """
 
 import re
-import socket
 import sys
 
-from stack_advisor import StackAdvisor
+from stack_advisor import DefaultStackAdvisor
 
-class HDP206StackAdvisor(StackAdvisor):
+class HDP206StackAdvisor(DefaultStackAdvisor):
 
-  def recommendComponentLayout(self, services, hosts):
-    """
-    Returns Services object with hostnames array populated for components
-    If hostnames are populated for some components (partial blueprint) - these components will not be processed
-    """
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
-    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
-
-    recommendations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "hosts": hostsList,
-      "services": servicesList,
-      "recommendations": {
-        "blueprint": {
-          "host_groups": [ ]
-        },
-        "blueprint_cluster_binding": {
-          "host_groups": [ ]
-        }
-      }
-    }
-
-    hostsComponentsMap = {}
-
-    #extend 'hostsComponentsMap' with MASTER components
-    for service in services["services"]:
-      masterComponents = [component for component in service["components"] if isMaster(component)]
-      for component in masterComponents:
-        componentName = component["StackServiceComponents"]["component_name"]
-        hostsForComponent = []
-
-        if isAlreadyPopulated(component):
-          hostsForComponent = component["StackServiceComponents"]["hostnames"]
-        else:
-          availableHosts = hostsList
-          if len(hostsList) > 1 and self.isNotPreferableOnAmbariServerHost(component):
-            availableHosts = [hostName for hostName in hostsList if not isLocalHost(hostName)]
-
-          if isMasterWithMultipleInstances(component):
-            hostsCount = defaultNoOfMasterHosts(component)
-            if hostsCount > 1: # get first 'hostsCount' available hosts
-              if len(availableHosts) < hostsCount:
-                hostsCount = len(availableHosts)
-              hostsForComponent = availableHosts[:hostsCount]
-            else:
-              hostsForComponent = [self.getHostForComponent(component, availableHosts)]
-          else:
-            hostsForComponent = [self.getHostForComponent(component, availableHosts)]
-
-        #extend 'hostsComponentsMap' with 'hostsForComponent'
-        for hostName in hostsForComponent:
-          if hostName not in hostsComponentsMap:
-            hostsComponentsMap[hostName] = []
-          hostsComponentsMap[hostName].append( { "name":componentName } )
-
-    #extend 'hostsComponentsMap' with Slave and Client Components
-    componentsListList = [service["components"] for service in services["services"]]
-    componentsList = [item for sublist in componentsListList for item in sublist]
-    usedHostsListList = [component["StackServiceComponents"]["hostnames"] for component in componentsList if not self.isNotValuable(component)]
-    utilizedHosts = [item for sublist in usedHostsListList for item in sublist]
-    freeHosts = [hostName for hostName in hostsList if hostName not in utilizedHosts]
-
-    for service in services["services"]:
-      slaveClientComponents = [component for component in service["components"] if isSlave(component) or isClient(component)]
-      for component in slaveClientComponents:
-        componentName = component["StackServiceComponents"]["component_name"]
-        hostsForComponent = []
-
-        if isAlreadyPopulated(component):
-          hostsForComponent = component["StackServiceComponents"]["hostnames"]
-        elif component["StackServiceComponents"]["cardinality"] == "ALL":
-          hostsForComponent = hostsList
-        else:
-          if len(freeHosts) == 0:
-            hostsForComponent = hostsList[-1:]
-          else: # len(freeHosts) >= 1
-            hostsForComponent = freeHosts
-            if isClient(component):
-              hostsForComponent = freeHosts[0:1]
-
-        #extend 'hostsComponentsMap' with 'hostsForComponent'
-        for hostName in hostsForComponent:
-          if hostName not in hostsComponentsMap:
-            hostsComponentsMap[hostName] = []
-          hostsComponentsMap[hostName].append( { "name": componentName } )
-
-    #prepare 'host-group's from 'hostsComponentsMap'
-    host_groups = recommendations["recommendations"]["blueprint"]["host_groups"]
-    bindings = recommendations["recommendations"]["blueprint_cluster_binding"]["host_groups"]
-    index = 0
-    for key in hostsComponentsMap.keys():
-      index += 1
-      host_group_name = "host-group-{0}".format(index)
-      host_groups.append( { "name": host_group_name, "components": hostsComponentsMap[key] } )
-      bindings.append( { "name": host_group_name, "hosts": [{ "fqdn": socket.getfqdn(key) }] } )
-
-    return recommendations
-  pass
-
-  def getHostForComponent(self, component, hostsList):
-    componentName = component["StackServiceComponents"]["component_name"]
-    scheme = self.defineSelectionScheme(componentName)
-
-    if len(hostsList) == 1:
-      return hostsList[0]
-    else:
-      for key in scheme.keys():
-        if isinstance(key, ( int, long )):
-          if len(hostsList) < key:
-            return hostsList[scheme[key]]
-      return hostsList[scheme['else']]
-
-  def defineSelectionScheme(self, componentName):
-    scheme = self.selectionScheme(componentName)
-    if scheme is None:
-      scheme = {"else": 0}
-    return scheme
-
-  def selectionScheme(self, componentName):
-    return {
-      'NAMENODE': {"else": 0},
-      'SECONDARY_NAMENODE': {"else": 1},
-      'HBASE_MASTER': {6: 0, 31: 2, "else": 3},
-
-      'HISTORYSERVER': {31: 1, "else": 2},
-      'RESOURCEMANAGER': {31: 1, "else": 2},
-
-      'OOZIE_SERVER': {6: 1, 31: 2, "else": 3},
-
-      'HIVE_SERVER': {6: 1, 31: 2, "else": 4},
-      'HIVE_METASTORE': {6: 1, 31: 2, "else": 4},
-      'WEBHCAT_SERVER': {6: 1, 31: 2, "else": 4},
-      }.get(componentName, None)
-
-  def isNotPreferableOnAmbariServerHost(self, component):
-    componentName = component["StackServiceComponents"]["component_name"]
-    service = ['GANGLIA_SERVER', 'NAGIOS_SERVER']
-    return componentName in service
-
-  def validateComponentLayout(self, services, hosts):
+  def getLayoutValidationItems(self, services, hosts):
     """Returns array of Validation objects about issues with hostnames components assigned to"""
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-
-    validations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "items": [ ]
-    }
-    items = validations["items"]
+    items = []
 
     # Validating NAMENODE and SECONDARY_NAMENODE are on different hosts if possible
     hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
     hostsCount = len(hostsList)
-    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
 
     componentsListList = [service["components"] for service in services["services"]]
     componentsList = [item for sublist in componentsListList for item in sublist]
@@ -204,10 +54,6 @@ class HDP206StackAdvisor(StackAdvisor):
            componentHostsCount = len(component["StackServiceComponents"]["hostnames"])
          cardinality = str(component["StackServiceComponents"]["cardinality"])
          # cardinality types: null, 1+, 1-2, 1, ALL
-         hostsMax = -sys.maxint - 1
-         hostsMin = sys.maxint
-         hostsMin = 0
-         hostsMax = 0
          if "+" in cardinality:
            hostsMin = int(cardinality[:-1])
            hostsMax = sys.maxint
@@ -232,54 +78,13 @@ class HDP206StackAdvisor(StackAdvisor):
     for host in nonUsedHostsList:
       items.append( { "type": 'host-component', "level": 'ERROR', "message": 'Host is not used', "host": str(host) } )
 
-    return validations
-  pass
-
-  def isNotValuable(self, component):
-    componentName = component["StackServiceComponents"]["component_name"]
-    service = ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR']
-    return componentName in service
+    return items
 
-  def recommendConfigurations(self, services, hosts):
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
-    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
-    components = [component["StackServiceComponents"]["component_name"]
-                  for service in services["services"]
-                  for component in service["components"]]
-
-    clusterData = self.getClusterData(servicesList, hosts, components)
-
-    recommendations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "hosts": hostsList,
-      "services": servicesList,
-      "recommendations": {
-        "blueprint": {
-          "configurations": {},
-          "host_groups": []
-        },
-        "blueprint_cluster_binding": {
-          "host_groups": []
-        }
-      }
-    }
-
-    configurations = recommendations["recommendations"]["blueprint"]["configurations"]
-
-    for service in servicesList:
-      calculation = self.recommendServiceConfigurations(service)
-      if calculation is not None:
-        calculation(configurations, clusterData)
-
-    return recommendations
-
-  def recommendServiceConfigurations(self, service):
+  def getServiceConfiguratorDict(self):
     return {
       "YARN": self.recommendYARNConfigurations,
       "MAPREDUCE2": self.recommendMapReduce2Configurations
-    }.get(service, None)
+    }
 
   def putProperty(self, config, configType):
     config[configType] = {"properties": {}}
@@ -379,17 +184,9 @@ class HDP206StackAdvisor(StackAdvisor):
 
     return cluster
 
-
-  def validateConfigurations(self, services, hosts):
+  def getConfigurationsValidationItems(self, services, hosts):
     """Returns array of Validation objects about issues with configuration values provided in services"""
-    stackName = services["Versions"]["stack_name"]
-    stackVersion = services["Versions"]["stack_version"]
-
-    validations = {
-      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
-      "items": [ ]
-    }
-    items = validations["items"]
+    items = []
 
     recommendations = self.recommendConfigurations(services, hosts)
     recommendedDefaults = recommendations["recommendations"]["blueprint"]["configurations"]
@@ -406,22 +203,24 @@ class HDP206StackAdvisor(StackAdvisor):
           if siteProperties is not None:
             resultItems = method(siteProperties, recommendedDefaults[siteName]["properties"])
             items.extend(resultItems)
-    return validations
-    pass
+    return items
 
-  def validateServiceConfigurations(self, serviceName):
+  def getServiceConfigurationValidators(self):
     return {
       "MAPREDUCE2": ["mapred-site", self.validateMapReduce2Configurations],
       "YARN": ["yarn-site", self.validateYARNConfigurations]
-    }.get(serviceName, None)
+    }
+
+  def validateServiceConfigurations(self, serviceName):
+    return self.getServiceConfigurationValidators().get(serviceName, None)
 
   def toConfigurationValidationProblems(self, validationProblems, siteName):
     result = []
     for validationProblem in validationProblems:
       validationItem = validationProblem.get("item", None)
       if validationItem is not None:
-        problem = { "type": 'configuration', "level": validationItem["level"], "message": validationItem["message"],
-                  "config-type": siteName, "config-name": validationProblem["config-name"] }
+        problem = {"type": 'configuration', "level": validationItem["level"], "message": validationItem["message"],
+                   "config-type": siteName, "config-name": validationProblem["config-name"] }
         result.append(problem)
     return result
 
@@ -476,6 +275,36 @@ class HDP206StackAdvisor(StackAdvisor):
                         {"config-name": 'yarn.scheduler.maximum-allocation-mb', "item": self.validatorLessThenDefaultValue(properties, recommendedDefaults, 'yarn.scheduler.maximum-allocation-mb')} ]
     return self.toConfigurationValidationProblems(validationItems, "yarn-site")
 
+  def getMastersWithMultipleInstances(self):
+    return ['ZOOKEEPER_SERVER', 'HBASE_MASTER']
+
+  def getNotValuableComponents(self):
+    return ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR']
+
+  def getNotPreferableOnServerComponents(self):
+    return ['GANGLIA_SERVER', 'NAGIOS_SERVER']
+
+  def getCardinalitiesDict(self):
+    return {
+      'ZOOKEEPER_SERVER': {"min": 3},
+      'HBASE_MASTER': {"min": 1},
+      }
+
+  def selectionSchemes(self):
+    return {
+      'NAMENODE': {"else": 0},
+      'SECONDARY_NAMENODE': {"else": 1},
+      'HBASE_MASTER': {6: 0, 31: 2, "else": 3},
+
+      'HISTORYSERVER': {31: 1, "else": 2},
+      'RESOURCEMANAGER': {31: 1, "else": 2},
+
+      'OOZIE_SERVER': {6: 1, 31: 2, "else": 3},
+
+      'HIVE_SERVER': {6: 1, 31: 2, "else": 4},
+      'HIVE_METASTORE': {6: 1, 31: 2, "else": 4},
+      'WEBHCAT_SERVER': {6: 1, 31: 2, "else": 4},
+      }
 
 # Validation helper methods
 def getSiteProperties(configurations, siteName):
@@ -519,45 +348,4 @@ def formatXmxSizeToBytes(value):
     modifier == 't': 1024 * 1024 * 1024 * 1024,
     modifier == 'p': 1024 * 1024 * 1024 * 1024 * 1024
     }[1]
-  return to_number(value) * m
-
-
-# Recommendation helper methods
-def isAlreadyPopulated(component):
-  if component["StackServiceComponents"]["hostnames"] is not None:
-    return len(component["StackServiceComponents"]["hostnames"]) > 0
-  return False
-
-def isClient(component):
-  return component["StackServiceComponents"]["component_category"] == 'CLIENT'
-
-def isSlave(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  isSlave = component["StackServiceComponents"]["component_category"] == 'SLAVE'
-  return isSlave
-
-def isMaster(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  isMaster = component["StackServiceComponents"]["is_master"]
-  return isMaster
-
-def isLocalHost(hostName):
-  return socket.getfqdn(hostName) == socket.getfqdn()
-
-def isMasterWithMultipleInstances(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  masters = ['ZOOKEEPER_SERVER', 'HBASE_MASTER']
-  return componentName in masters
-
-def defaultNoOfMasterHosts(component):
-  componentName = component["StackServiceComponents"]["component_name"]
-  return cardinality(componentName)[min]
-
-
-# Helper dictionaries
-def cardinality(componentName):
-  return {
-    'ZOOKEEPER_SERVER': {min: 3},
-    'HBASE_MASTER': {min: 1},
-    }.get(componentName, {min:1, max:1})
-
+  return to_number(value) * m
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/stacks/HDP/2.1/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.1/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.1/services/stack_advisor.py
index 98fee5d..bcf3f61 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.1/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.1/services/stack_advisor.py
@@ -17,10 +17,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 """
 
-import socket
-
-from stack_advisor import StackAdvisor
-
 class HDP21StackAdvisor(HDP206StackAdvisor):
 
   def recommendServiceConfigurations(self, service):
@@ -58,35 +54,45 @@ class HDP21StackAdvisor(HDP206StackAdvisor):
                    "-server -Xmx" + str(int(0.8 * clusterData["amMemory"]))
                    + "m -Djava.net.preferIPv4Stack=true -XX:+UseNUMA -XX:+UseParallelGC")
 
-  def isNotPreferableOnAmbariServerHost(self, component):
-    componentName = component["StackServiceComponents"]["component_name"]
-    service = ['STORM_UI_SERVER', 'DRPC_SERVER', 'STORM_REST_API', 'NIMBUS', 'GANGLIA_SERVER', 'NAGIOS_SERVER']
-    return componentName in service
+  def getNotPreferableOnServerComponents(self):
+    return ['STORM_UI_SERVER', 'DRPC_SERVER', 'STORM_REST_API', 'NIMBUS', 'GANGLIA_SERVER', 'NAGIOS_SERVER']
 
-  def isNotValuable(self, component):
-    componentName = component["StackServiceComponents"]["component_name"]
-    service = ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR', 'APP_TIMELINE_SERVER']
-    return componentName in service
+  def getNotValuableComponents(self):
+    return ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR', 'APP_TIMELINE_SERVER']
 
-  def selectionScheme(self, componentName):
-    scheme = super(HDP21StackAdvisor, self).selectionScheme(componentName)
-    if scheme is None:
-      return {
+  def selectionSchemes(self):
+    return {
+      'NAMENODE': {"else": 0},
+      'SECONDARY_NAMENODE': {"else": 1},
+      'HBASE_MASTER': {6: 0, 31: 2, "else": 3},
+
+      'HISTORYSERVER': {31: 1, "else": 2},
+      'RESOURCEMANAGER': {31: 1, "else": 2},
+
+      'OOZIE_SERVER': {6: 1, 31: 2, "else": 3},
+
+      'HIVE_SERVER': {6: 1, 31: 2, "else": 4},
+      'HIVE_METASTORE': {6: 1, 31: 2, "else": 4},
+      'WEBHCAT_SERVER': {6: 1, 31: 2, "else": 4},
+      }
+
+  def selectionScheme(self):
+    parentSchemes = super(HDP21StackAdvisor, self).selectionSchemes()
+    childSchemes = {
         'APP_TIMELINE_SERVER': {31: 1, "else": 2},
         'FALCON_SERVER': {6: 1, 31: 2, "else": 3}
-        }.get(componentName, None)
-    else:
-      return scheme
-
-  def validateServiceConfigurations(self, serviceName):
-    validator = super(HDP21StackAdvisor, self).validateServiceConfigurations(serviceName)
-    if validator is None:
-      return {
-        "HIVE": ["hive-site", self.validateHiveConfigurations],
-        "TEZ": ["tez-site", self.validateTezConfigurations]
-      }.get(serviceName, None)
-    else:
-      return validator
+    }
+    parentSchemes.update(childSchemes)
+    return parentSchemes
+
+  def getServiceConfigurationValidators(self):
+    parentValidators = super(HDP21StackAdvisor, self).getServiceConfigurationValidators()
+    childValidators = {
+      "HIVE": ["hive-site", self.validateHiveConfigurations],
+      "TEZ": ["tez-site", self.validateTezConfigurations]
+    }
+    parentValidators.update(childValidators)
+    return parentValidators
 
   def validateHiveConfigurations(self, properties, recommendedDefaults):
     validationItems = [ {"config-name": 'hive.tez.container.size', "item": self.validatorLessThenDefaultValue(properties, recommendedDefaults, 'hive.tez.container.size')},

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/main/resources/stacks/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/stack_advisor.py b/ambari-server/src/main/resources/stacks/stack_advisor.py
index 5f66fff..dca2834 100644
--- a/ambari-server/src/main/resources/stacks/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/stack_advisor.py
@@ -17,6 +17,8 @@ See the License for the specific language governing permissions and
 limitations under the License.
 """
 
+import socket
+
 class StackAdvisor(object):
 
   def recommendComponentLayout(self, services, hosts):
@@ -35,3 +37,272 @@ class StackAdvisor(object):
     """Returns array of Validation objects about issues with configuration values provided in services"""
     pass
 
+class DefaultStackAdvisor(StackAdvisor):
+
+  def recommendComponentLayout(self, services, hosts):
+    """Returns Services object with hostnames array populated for components"""
+
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
+
+    layoutRecommendations = self.provideLayout(services, hosts)
+
+    recommendations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "hosts": hostsList,
+      "services": servicesList,
+      "recommendations": layoutRecommendations
+    }
+
+    return recommendations
+
+  def provideLayout(self, services, hosts):
+
+    recommendations = {
+      "blueprint": {
+        "host_groups": [ ]
+      },
+      "blueprint_cluster_binding": {
+        "host_groups": [ ]
+      }
+    }
+
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+
+    hostsComponentsMap = {}
+    for hostName in hostsList:
+      if hostName not in hostsComponentsMap:
+        hostsComponentsMap[hostName] = []
+
+    #extend 'hostsComponentsMap' with MASTER components
+    for service in services["services"]:
+      masterComponents = [component for component in service["components"] if self.isMaster(component)]
+      for component in masterComponents:
+        componentName = component["StackServiceComponents"]["component_name"]
+
+        if self.isAlreadyPopulated(component):
+          hostsForComponent = component["StackServiceComponents"]["hostnames"]
+        else:
+          availableHosts = hostsList
+          if len(hostsList) > 1 and self.isNotPreferableOnAmbariServerHost(component):
+            availableHosts = [hostName for hostName in hostsList if not self.isLocalHost(hostName)]
+
+          if self.isMasterWithMultipleInstances(component):
+            hostsCount = self.defaultNoOfMasterHosts(component)
+            if hostsCount > 1: # get first 'hostsCount' available hosts
+              if len(availableHosts) < hostsCount:
+                hostsCount = len(availableHosts)
+              hostsForComponent = availableHosts[:hostsCount]
+            else:
+              hostsForComponent = [self.getHostForComponent(component, availableHosts, hostsComponentsMap)]
+          else:
+            hostsForComponent = [self.getHostForComponent(component, availableHosts, hostsComponentsMap)]
+
+        #extend 'hostsComponentsMap' with 'hostsForComponent'
+        for hostName in hostsForComponent:
+          hostsComponentsMap[hostName].append( { "name":componentName } )
+
+    #extend 'hostsComponentsMap' with Slave and Client Components
+    componentsListList = [service["components"] for service in services["services"]]
+    componentsList = [item for sublist in componentsListList for item in sublist]
+    usedHostsListList = [component["StackServiceComponents"]["hostnames"] for component in componentsList if not self.isNotValuable(component)]
+    utilizedHosts = [item for sublist in usedHostsListList for item in sublist]
+    freeHosts = [hostName for hostName in hostsList if hostName not in utilizedHosts]
+
+    for service in services["services"]:
+      slaveClientComponents = [component for component in service["components"]
+                               if self.isSlave(component) or self.isClient(component)]
+      for component in slaveClientComponents:
+        componentName = component["StackServiceComponents"]["component_name"]
+
+        if self.isAlreadyPopulated(component):
+          hostsForComponent = component["StackServiceComponents"]["hostnames"]
+        elif component["StackServiceComponents"]["cardinality"] == "ALL":
+          hostsForComponent = hostsList
+        else:
+          if len(freeHosts) == 0:
+            hostsForComponent = hostsList[-1:]
+          else: # len(freeHosts) >= 1
+            hostsForComponent = freeHosts
+            if self.isClient(component):
+              hostsForComponent = freeHosts[0:1]
+
+        #extend 'hostsComponentsMap' with 'hostsForComponent'
+        for hostName in hostsForComponent:
+          if hostName not in hostsComponentsMap:
+            hostsComponentsMap[hostName] = []
+          hostsComponentsMap[hostName].append( { "name": componentName } )
+
+    #prepare 'host-group's from 'hostsComponentsMap'
+    host_groups = recommendations["blueprint"]["host_groups"]
+    bindings = recommendations["blueprint_cluster_binding"]["host_groups"]
+    index = 0
+    for key in hostsComponentsMap.keys():
+      index += 1
+      host_group_name = "host-group-{0}".format(index)
+      host_groups.append( { "name": host_group_name, "components": hostsComponentsMap[key] } )
+      bindings.append( { "name": host_group_name, "hosts": [{ "fqdn": socket.getfqdn(key) }] } )
+
+    return recommendations
+  pass
+
+  def prepareValidationResponse(self, services, validationItems):
+    """Returns array of Validation objects about issues with hostnames components assigned to"""
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+
+    validations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "items": validationItems
+    }
+
+    return validations
+
+  def validateComponentLayout(self, services, hosts):
+    """Returns array of Validation objects about issues with hostnames components assigned to"""
+    validationItems = self.getLayoutValidationItems(services, hosts)
+    return self.prepareValidationResponse(services, validationItems)
+
+  def validateConfigurations(self, services, hosts):
+    """Returns array of Validation objects about issues with hostnames components assigned to"""
+    validationItems = self.getConfigurationsValidationItems(services, hosts)
+    return self.prepareValidationResponse(services, validationItems)
+
+  def getLayoutValidationItems(self, services, hosts):
+    return []
+
+  def getClusterData(self, servicesList, hosts, components):
+    pass
+
+  def getConfigurationsValidationItems(self, services, hosts):
+    return []
+
+  def recommendConfigurations(self, services, hosts):
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
+    components = [component["StackServiceComponents"]["component_name"]
+                  for service in services["services"]
+                  for component in service["components"]]
+
+    clusterData = self.getClusterData(servicesList, hosts, components)
+
+    recommendations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "hosts": hostsList,
+      "services": servicesList,
+      "recommendations": {
+        "blueprint": {
+          "configurations": {},
+          "host_groups": []
+        },
+        "blueprint_cluster_binding": {
+          "host_groups": []
+        }
+      }
+    }
+
+    configurations = recommendations["recommendations"]["blueprint"]["configurations"]
+
+    for service in servicesList:
+      calculation = self.recommendServiceConfigurations(service)
+      if calculation is not None:
+        calculation(configurations, clusterData)
+
+    return recommendations
+
+  def recommendServiceConfigurations(self, service):
+    return self.getServiceConfiguratorDict().get(service, None)
+
+  def getServiceConfiguratorDict(self):
+    return {}
+
+  # Recommendation helper methods
+  def isAlreadyPopulated(self, component):
+    hostnames = self.getComponentAttribute(component, "hostnames")
+    if hostnames is not None:
+      return len(hostnames) > 0
+    return False
+
+  def isClient(self, component):
+    return self.getComponentAttribute(component, "component_category") == 'CLIENT'
+
+  def isSlave(self, component):
+    return self.getComponentAttribute(component, "component_category") == 'SLAVE'
+
+  def isMaster(self, component):
+    return self.getComponentAttribute(component, "is_master")
+
+  def getComponentAttribute(self, component, attribute):
+    serviceComponent = component.get("StackServiceComponents", None)
+    if serviceComponent is None:
+      return None
+    return serviceComponent.get(attribute, None)
+
+  def isLocalHost(self, hostName):
+    return socket.getfqdn(hostName) == socket.getfqdn()
+
+  def isMasterWithMultipleInstances(self, component):
+    componentName = self.getComponentName(component)
+    masters = self.getMastersWithMultipleInstances()
+    return componentName in masters
+
+  def isNotValuable(self, component):
+    componentName = self.getComponentName(component)
+    service = self.getNotValuableComponents()
+    return componentName in service
+
+  def defaultNoOfMasterHosts(self, component):
+    componentName = self.getComponentName(component)
+    return self.cardinality(componentName)["min"]
+
+  # Helper dictionaries
+  def cardinality(self, componentName):
+    return self.getCardinalitiesDict().get(componentName, {"min": 1, "max": 1})
+
+  def getHostForComponent(self, component, hostsList, hostsComponentsMap):
+    componentName = self.getComponentName(component)
+
+    if len(hostsList) == 1:
+      return hostsList[0]
+    else:
+      scheme = self.defineSelectionScheme(componentName)
+      if scheme is not None:
+        for key in scheme.keys():
+          if isinstance(key, ( int, long )):
+            if len(hostsList) < key:
+              return hostsList[scheme[key]]
+      return self.getLeastOccupiedHost(hostsList, hostsComponentsMap)
+
+  def getLeastOccupiedHost(self, hostsList, hostComponentsMap):
+    hostOccupations = dict((host, len(components)) for host, components in hostComponentsMap.iteritems() if host in hostsList)
+    return min(hostOccupations, key=hostOccupations.get)
+
+  def defineSelectionScheme(self, componentName):
+    return self.selectionSchemes().get(componentName, None)
+
+  def getComponentName(self, component):
+    return self.getComponentAttribute(component, "component_name")
+
+  def isNotPreferableOnAmbariServerHost(self, component):
+    componentName = self.getComponentName(component)
+    service = self.getNotPreferableOnServerComponents()
+    return componentName in service
+
+  def getMastersWithMultipleInstances(self):
+    return []
+
+  def getNotValuableComponents(self):
+    return []
+
+  def getNotPreferableOnServerComponents(self):
+    return []
+
+  def getCardinalitiesDict(self):
+    return {}
+
+  def selectionSchemes(self):
+    return {}

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/test/python/TestStackAdvisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestStackAdvisor.py b/ambari-server/src/test/python/TestStackAdvisor.py
index 5a1a242..3f56816 100644
--- a/ambari-server/src/test/python/TestStackAdvisor.py
+++ b/ambari-server/src/test/python/TestStackAdvisor.py
@@ -38,40 +38,41 @@ class TestStackAdvisorInitialization(TestCase):
     instantiate_stack_advisor_method = getattr(self.stack_advisor, instantiate_stack_advisor_method_name)
     stack_advisor = instantiate_stack_advisor_method("XYZ", "1.0.1", ["1.0.0"])
     self.assertEquals("XYZ101StackAdvisor", stack_advisor.__class__.__name__)
-    services = {"Versions":
-                  {
-                    "stack_name":"XYZ",
-                    "stack_version":"1.0.1"
-                  },
-                "services":[
-                  {
-                    "StackServices":{
-                      "service_name":"YARN"
-                    },
-                    "components":[
-                      {
-                        "StackServiceComponents": {
-                          "component_name": "RESOURCEMANAGER"
-                        }
-                      },
-                      {
-                        "StackServiceComponents": {
-                          "component_name": "APP_TIMELINE_SERVER"
-                        }
-                      },
-                      {
-                        "StackServiceComponents": {
-                          "component_name":"YARN_CLIENT"
-                        }
-                      },
-                      {
-                        "StackServiceComponents": {
-                          "component_name": "NODEMANAGER"
-                        }
-                      }
-                    ]
-                  }
-                ]
+    services = {
+      "Versions":
+        {
+          "stack_name":"XYZ",
+          "stack_version":"1.0.1"
+        },
+      "services":[
+        {
+          "StackServices":{
+            "service_name":"YARN"
+          },
+          "components":[
+            {
+              "StackServiceComponents": {
+                "component_name": "RESOURCEMANAGER"
+              }
+            },
+            {
+              "StackServiceComponents": {
+                "component_name": "APP_TIMELINE_SERVER"
+              }
+            },
+            {
+              "StackServiceComponents": {
+                "component_name":"YARN_CLIENT"
+              }
+            },
+            {
+              "StackServiceComponents": {
+                "component_name": "NODEMANAGER"
+              }
+            }
+          ]
+        }
+      ]
     }
     hosts= {
       "items": [
@@ -84,10 +85,258 @@ class TestStackAdvisorInitialization(TestCase):
     '''Check that value is populated from child class, not parent'''
     self.assertEquals("-Xmx101m", yarn_configs["yarn.nodemanager.resource.memory-mb"])
 
-  def test_stackAdvisorSuperClassIsFoundAndReturnedAsDefaultImpl(self):
+  def test_stackAdvisorDefaultImpl(self):
     instantiate_stack_advisor_method_name = 'instantiateStackAdvisor'
     instantiate_stack_advisor_method = getattr(self.stack_advisor, instantiate_stack_advisor_method_name)
     '''Not existent stack - to return default implementation'''
     default_stack_advisor = instantiate_stack_advisor_method("HDP1", "2.0.6", [])
-    self.assertEquals("StackAdvisor", default_stack_advisor.__class__.__name__)
-
+    self.assertEquals("DefaultStackAdvisor", default_stack_advisor.__class__.__name__)
+    services = {
+      "Versions":
+        {
+          "stack_name":"HDP1",
+          "stack_version":"2.0.6"
+        },
+      "services" : [
+        {
+          "StackServices" : {
+            "service_name" : "GANGLIA",
+            "service_version" : "3.5.0",
+          },
+          "components" : [
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "ALL",
+                "component_name" : "GANGLIA_MONITOR",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1",
+                "component_name" : "GANGLIA_SERVER",
+                "is_master" : True,
+                "hostnames" : [ ]
+              }
+            }
+          ]
+        },
+        {
+          "StackServices" : {
+            "service_name" : "HBASE",
+            "service_version" : "0.98.0.2.1"
+          },
+          "components" : [
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_name" : "HBASE_CLIENT",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_name" : "HBASE_MASTER",
+                "is_master" : True,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_name" : "HBASE_REGIONSERVER",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            }
+          ]
+        },
+        {
+          "StackServices" : {
+            "service_name" : "HDFS",
+            "service_version" : "2.4.0.2.1"
+          },
+          "components" : [
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_name" : "DATANODE",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            }, {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_name" : "HDFS_CLIENT",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            }, {
+              "StackServiceComponents" : {
+                "cardinality" : "0+",
+                "component_name" : "JOURNALNODE",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1-2",
+                "component_name" : "NAMENODE",
+                "is_master" : True,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1",
+                "component_name" : "SECONDARY_NAMENODE",
+                "is_master" : True,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "0+",
+                "component_name" : "ZKFC",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            }
+          ]
+        },
+        {
+          "StackServices" : {
+            "service_name" : "PIG",
+            "service_version" : "0.12.1.2.1"
+          },
+          "components" : [
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "0+",
+                "component_name" : "PIG",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            }
+          ]
+        },
+        {
+          "StackServices" : {
+            "service_name" : "TEZ",
+            "service_version" : "0.4.0.2.1"
+          },
+          "components" : [
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "0+",
+                "component_name" : "TEZ_CLIENT",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            }
+          ]
+        },
+        {
+          "StackServices" : {
+            "service_name" : "ZOOKEEPER",
+            "service_version" : "3.4.5.2.1",
+          },
+          "components" : [
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_category" : "CLIENT",
+                "component_name" : "ZOOKEEPER_CLIENT",
+                "is_master" : False,
+                "hostnames" : [ ]
+              }
+            },
+            {
+              "StackServiceComponents" : {
+                "cardinality" : "1+",
+                "component_name" : "ZOOKEEPER_SERVER",
+                "is_master" : True,
+                "hostnames" : [ ]
+             }
+           }
+          ]
+        }
+      ],
+      "configurations" : {}
+    }
+    hosts= {
+      "items": [
+        {"Hosts": {"host_name": "host1"}},
+        {"Hosts": {"host_name": "host2"}}
+      ]
+    }
+    actualValidateConfigResponse = default_stack_advisor.validateConfigurations(services, hosts)
+    actualValidateLayoutResponse = default_stack_advisor.validateComponentLayout(services, hosts)
+    expectedValidationResponse = {
+      "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"},
+      "items": []
+    }
+    self.assertEquals(actualValidateConfigResponse, expectedValidationResponse)
+    self.assertEquals(actualValidateLayoutResponse, expectedValidationResponse)
+    actualRecommendConfigResponse = default_stack_advisor.recommendConfigurations(services, hosts)
+    expectedRecommendConfigResponse = {
+      "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"},
+      "hosts": ["host1", "host2"],
+      "services": ['GANGLIA', 'HBASE', 'HDFS', 'PIG', 'TEZ', 'ZOOKEEPER'],
+      "recommendations": {
+        "blueprint": {
+          "configurations": {},
+          "host_groups": []
+        },
+        "blueprint_cluster_binding": {
+          "host_groups": []
+        }
+      }
+    }
+    self.assertEquals(actualRecommendConfigResponse, expectedRecommendConfigResponse)
+    actualRecommendLayoutResponse = default_stack_advisor.recommendComponentLayout(services, hosts)
+    expectedRecommendLayoutResponse = {
+      "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"},
+      "hosts": ["host1", "host2"],
+      "services": ['GANGLIA', 'HBASE', 'HDFS', 'PIG', 'TEZ', 'ZOOKEEPER'],
+      "recommendations": {
+        "blueprint": {
+          "host_groups": [
+            {
+              "name": "host-group-1",
+              "components": [
+                {"name": "GANGLIA_SERVER"},
+                {"name": "NAMENODE"},
+                {"name": "ZOOKEEPER_SERVER"}
+              ]
+            },
+            {
+              "name": "host-group-2",
+              "components": [
+                {"name": "HBASE_MASTER"},
+                {"name": "SECONDARY_NAMENODE"},
+                {"name": "ZOOKEEPER_CLIENT"}
+              ]
+            }
+          ]
+        },
+        "blueprint_cluster_binding":
+          {
+            "host_groups": [
+              {
+                "name": "host-group-1",
+                "hosts": [{"fqdn": "host2"}]
+              },
+              {
+                "name": "host-group-2",
+                "hosts": [{"fqdn": "host1"}]
+              }
+            ]
+          }
+      }
+    }
+    self.assertEquals(actualRecommendLayoutResponse, expectedRecommendLayoutResponse)

http://git-wip-us.apache.org/repos/asf/ambari/blob/dc269bb1/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
index b1b9f7a..aa86242 100644
--- a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
@@ -35,7 +35,7 @@ class TestHDP206StackAdvisor(TestCase):
       stack_advisor_impl = imp.load_module('stack_advisor_impl', fp, hdp206StackAdvisorPath, ('.py', 'rb', imp.PY_SOURCE))
     clazz = getattr(stack_advisor_impl, hdp206StackAdvisorClassName)
     self.stackAdvisor = clazz()
-    
+
   def test_recommendationCardinalityALL(self):
     servicesInfo = [
       {


[10/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/api.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/api.rst b/ambari-common/src/main/python/jinja2/docs/api.rst
new file mode 100644
index 0000000..3bf8a94
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/api.rst
@@ -0,0 +1,787 @@
+API
+===
+
+.. module:: jinja2
+    :synopsis: public Jinja2 API
+
+This document describes the API to Jinja2 and not the template language.  It
+will be most useful as reference to those implementing the template interface
+to the application and not those who are creating Jinja2 templates.
+
+Basics
+------
+
+Jinja2 uses a central object called the template :class:`Environment`.
+Instances of this class are used to store the configuration, global objects
+and are used to load templates from the file system or other locations.
+Even if you are creating templates from strings by using the constructor of
+:class:`Template` class, an environment is created automatically for you,
+albeit a shared one.
+
+Most applications will create one :class:`Environment` object on application
+initialization and use that to load templates.  In some cases it's however
+useful to have multiple environments side by side, if different configurations
+are in use.
+
+The simplest way to configure Jinja2 to load templates for your application
+looks roughly like this::
+
+    from jinja2 import Environment, PackageLoader
+    env = Environment(loader=PackageLoader('yourapplication', 'templates'))
+
+This will create a template environment with the default settings and a
+loader that looks up the templates in the `templates` folder inside the
+`yourapplication` python package.  Different loaders are available
+and you can also write your own if you want to load templates from a
+database or other resources.
+
+To load a template from this environment you just have to call the
+:meth:`get_template` method which then returns the loaded :class:`Template`::
+
+    template = env.get_template('mytemplate.html')
+
+To render it with some variables, just call the :meth:`render` method::
+
+    print template.render(the='variables', go='here')
+
+Using a template loader rather then passing strings to :class:`Template`
+or :meth:`Environment.from_string` has multiple advantages.  Besides being
+a lot easier to use it also enables template inheritance.
+
+
+Unicode
+-------
+
+Jinja2 is using Unicode internally which means that you have to pass Unicode
+objects to the render function or bytestrings that only consist of ASCII
+characters.  Additionally newlines are normalized to one end of line
+sequence which is per default UNIX style (``\n``).
+
+Python 2.x supports two ways of representing string objects.  One is the
+`str` type and the other is the `unicode` type, both of which extend a type
+called `basestring`.  Unfortunately the default is `str` which should not
+be used to store text based information unless only ASCII characters are
+used.  With Python 2.6 it is possible to make `unicode` the default on a per
+module level and with Python 3 it will be the default.
+
+To explicitly use a Unicode string you have to prefix the string literal
+with a `u`: ``u'Hänsel und Gretel sagen Hallo'``.  That way Python will
+store the string as Unicode by decoding the string with the character
+encoding from the current Python module.  If no encoding is specified this
+defaults to 'ASCII' which means that you can't use any non ASCII identifier.
+
+To set a better module encoding add the following comment to the first or
+second line of the Python module using the Unicode literal::
+
+    # -*- coding: utf-8 -*-
+
+We recommend utf-8 as Encoding for Python modules and templates as it's
+possible to represent every Unicode character in utf-8 and because it's
+backwards compatible to ASCII.  For Jinja2 the default encoding of templates
+is assumed to be utf-8.
+
+It is not possible to use Jinja2 to process non-Unicode data.  The reason
+for this is that Jinja2 uses Unicode already on the language level.  For
+example Jinja2 treats the non-breaking space as valid whitespace inside
+expressions which requires knowledge of the encoding or operating on an
+Unicode string.
+
+For more details about Unicode in Python have a look at the excellent
+`Unicode documentation`_.
+
+Another important thing is how Jinja2 is handling string literals in
+templates.  A naive implementation would be using Unicode strings for
+all string literals but it turned out in the past that this is problematic
+as some libraries are typechecking against `str` explicitly.  For example
+`datetime.strftime` does not accept Unicode arguments.  To not break it
+completely Jinja2 is returning `str` for strings that fit into ASCII and
+for everything else `unicode`:
+
+>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
+>>> m.a
+'foo'
+>>> m.b
+u'f\xf6\xf6'
+
+
+.. _Unicode documentation: http://docs.python.org/dev/howto/unicode.html
+
+High Level API
+--------------
+
+The high-level API is the API you will use in the application to load and
+render Jinja2 templates.  The :ref:`low-level-api` on the other side is only
+useful if you want to dig deeper into Jinja2 or :ref:`develop extensions
+<jinja-extensions>`.
+
+.. autoclass:: Environment([options])
+    :members: from_string, get_template, select_template,
+              get_or_select_template, join_path, extend, compile_expression
+
+    .. attribute:: shared
+
+        If a template was created by using the :class:`Template` constructor
+        an environment is created automatically.  These environments are
+        created as shared environments which means that multiple templates
+        may have the same anonymous environment.  For all shared environments
+        this attribute is `True`, else `False`.
+
+    .. attribute:: sandboxed
+
+        If the environment is sandboxed this attribute is `True`.  For the
+        sandbox mode have a look at the documentation for the
+        :class:`~jinja2.sandbox.SandboxedEnvironment`.
+
+    .. attribute:: filters
+
+        A dict of filters for this environment.  As long as no template was
+        loaded it's safe to add new filters or remove old.  For custom filters
+        see :ref:`writing-filters`.  For valid filter names have a look at
+        :ref:`identifier-naming`.
+
+    .. attribute:: tests
+
+        A dict of test functions for this environment.  As long as no
+        template was loaded it's safe to modify this dict.  For custom tests
+        see :ref:`writing-tests`.  For valid test names have a look at
+        :ref:`identifier-naming`.
+
+    .. attribute:: globals
+
+        A dict of global variables.  These variables are always available
+        in a template.  As long as no template was loaded it's safe
+        to modify this dict.  For more details see :ref:`global-namespace`.
+        For valid object names have a look at :ref:`identifier-naming`.
+
+    .. automethod:: overlay([options])
+
+    .. method:: undefined([hint, obj, name, exc])
+
+        Creates a new :class:`Undefined` object for `name`.  This is useful
+        for filters or functions that may return undefined objects for
+        some operations.  All parameters except of `hint` should be provided
+        as keyword parameters for better readability.  The `hint` is used as
+        error message for the exception if provided, otherwise the error
+        message will be generated from `obj` and `name` automatically.  The exception
+        provided as `exc` is raised if something with the generated undefined
+        object is done that the undefined object does not allow.  The default
+        exception is :exc:`UndefinedError`.  If a `hint` is provided the
+        `name` may be ommited.
+
+        The most common way to create an undefined object is by providing
+        a name only::
+
+            return environment.undefined(name='some_name')
+
+        This means that the name `some_name` is not defined.  If the name
+        was from an attribute of an object it makes sense to tell the
+        undefined object the holder object to improve the error message::
+
+            if not hasattr(obj, 'attr'):
+                return environment.undefined(obj=obj, name='attr')
+
+        For a more complex example you can provide a hint.  For example
+        the :func:`first` filter creates an undefined object that way::
+
+            return environment.undefined('no first item, sequence was empty')            
+
+        If it the `name` or `obj` is known (for example because an attribute
+        was accessed) it shold be passed to the undefined object, even if
+        a custom `hint` is provided.  This gives undefined objects the
+        possibility to enhance the error message.
+
+.. autoclass:: Template
+    :members: module, make_module
+
+    .. attribute:: globals
+
+        The dict with the globals of that template.  It's unsafe to modify
+        this dict as it may be shared with other templates or the environment
+        that loaded the template.
+
+    .. attribute:: name
+
+        The loading name of the template.  If the template was loaded from a
+        string this is `None`.
+
+    .. attribute:: filename
+
+        The filename of the template on the file system if it was loaded from
+        there.  Otherwise this is `None`.
+
+    .. automethod:: render([context])
+
+    .. automethod:: generate([context])
+
+    .. automethod:: stream([context])
+
+
+.. autoclass:: jinja2.environment.TemplateStream()
+    :members: disable_buffering, enable_buffering, dump
+
+
+Autoescaping
+------------
+
+.. versionadded:: 2.4
+
+As of Jinja 2.4 the preferred way to do autoescaping is to enable the
+:ref:`autoescape-extension` and to configure a sensible default for
+autoescaping.  This makes it possible to enable and disable autoescaping
+on a per-template basis (HTML versus text for instance).
+
+Here a recommended setup that enables autoescaping for templates ending
+in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
+for all other extensions::
+
+    def guess_autoescape(template_name):
+        if template_name is None or '.' not in template_name:
+            return False
+        ext = template_name.rsplit('.', 1)[1]
+        return ext in ('html', 'htm', 'xml')
+
+    env = Environment(autoescape=guess_autoescape,
+                      loader=PackageLoader('mypackage'),
+                      extensions=['jinja2.ext.autoescape'])
+
+When implementing a guessing autoescape function, make sure you also
+accept `None` as valid template name.  This will be passed when generating
+templates from strings.
+
+Inside the templates the behaviour can be temporarily changed by using
+the `autoescape` block (see :ref:`autoescape-overrides`).
+
+
+.. _identifier-naming:
+
+Notes on Identifiers
+--------------------
+
+Jinja2 uses the regular Python 2.x naming rules.  Valid identifiers have to
+match ``[a-zA-Z_][a-zA-Z0-9_]*``.  As a matter of fact non ASCII characters
+are currently not allowed.  This limitation will probably go away as soon as
+unicode identifiers are fully specified for Python 3.
+
+Filters and tests are looked up in separate namespaces and have slightly
+modified identifier syntax.  Filters and tests may contain dots to group
+filters and tests by topic.  For example it's perfectly valid to add a
+function into the filter dict and call it `to.unicode`.  The regular
+expression for filter and test identifiers is
+``[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*```.
+
+
+Undefined Types
+---------------
+
+These classes can be used as undefined types.  The :class:`Environment`
+constructor takes an `undefined` parameter that can be one of those classes
+or a custom subclass of :class:`Undefined`.  Whenever the template engine is
+unable to look up a name or access an attribute one of those objects is
+created and returned.  Some operations on undefined values are then allowed,
+others fail.
+
+The closest to regular Python behavior is the `StrictUndefined` which
+disallows all operations beside testing if it's an undefined object.
+
+.. autoclass:: jinja2.Undefined()
+
+    .. attribute:: _undefined_hint
+
+        Either `None` or an unicode string with the error message for
+        the undefined object.
+
+    .. attribute:: _undefined_obj
+
+        Either `None` or the owner object that caused the undefined object
+        to be created (for example because an attribute does not exist).
+
+    .. attribute:: _undefined_name
+
+        The name for the undefined variable / attribute or just `None`
+        if no such information exists.
+
+    .. attribute:: _undefined_exception
+
+        The exception that the undefined object wants to raise.  This
+        is usually one of :exc:`UndefinedError` or :exc:`SecurityError`.
+
+    .. method:: _fail_with_undefined_error(\*args, \**kwargs)
+
+        When called with any arguments this method raises
+        :attr:`_undefined_exception` with an error message generated
+        from the undefined hints stored on the undefined object.
+
+.. autoclass:: jinja2.DebugUndefined()
+
+.. autoclass:: jinja2.StrictUndefined()
+
+Undefined objects are created by calling :attr:`undefined`.
+
+.. admonition:: Implementation
+
+    :class:`Undefined` objects are implemented by overriding the special
+    `__underscore__` methods.  For example the default :class:`Undefined`
+    class implements `__unicode__` in a way that it returns an empty
+    string, however `__int__` and others still fail with an exception.  To
+    allow conversion to int by returning ``0`` you can implement your own::
+
+        class NullUndefined(Undefined):
+            def __int__(self):
+                return 0
+            def __float__(self):
+                return 0.0
+
+    To disallow a method, just override it and raise
+    :attr:`~Undefined._undefined_exception`.  Because this is a very common
+    idom in undefined objects there is the helper method
+    :meth:`~Undefined._fail_with_undefined_error` that does the error raising
+    automatically.  Here a class that works like the regular :class:`Undefined`
+    but chokes on iteration::
+
+        class NonIterableUndefined(Undefined):
+            __iter__ = Undefined._fail_with_undefined_error
+
+
+The Context
+-----------
+
+.. autoclass:: jinja2.runtime.Context()
+    :members: resolve, get_exported, get_all
+
+    .. attribute:: parent
+
+        A dict of read only, global variables the template looks up.  These
+        can either come from another :class:`Context`, from the
+        :attr:`Environment.globals` or :attr:`Template.globals` or points
+        to a dict created by combining the globals with the variables
+        passed to the render function.  It must not be altered.
+
+    .. attribute:: vars
+
+        The template local variables.  This list contains environment and
+        context functions from the :attr:`parent` scope as well as local
+        modifications and exported variables from the template.  The template
+        will modify this dict during template evaluation but filters and
+        context functions are not allowed to modify it.
+
+    .. attribute:: environment
+
+        The environment that loaded the template.
+
+    .. attribute:: exported_vars
+
+        This set contains all the names the template exports.  The values for
+        the names are in the :attr:`vars` dict.  In order to get a copy of the
+        exported variables as dict, :meth:`get_exported` can be used.
+
+    .. attribute:: name
+
+        The load name of the template owning this context.
+
+    .. attribute:: blocks
+
+        A dict with the current mapping of blocks in the template.  The keys
+        in this dict are the names of the blocks, and the values a list of
+        blocks registered.  The last item in each list is the current active
+        block (latest in the inheritance chain).
+
+    .. attribute:: eval_ctx
+
+        The current :ref:`eval-context`.
+
+    .. automethod:: jinja2.runtime.Context.call(callable, \*args, \**kwargs)
+
+
+.. admonition:: Implementation
+
+    Context is immutable for the same reason Python's frame locals are
+    immutable inside functions.  Both Jinja2 and Python are not using the
+    context / frame locals as data storage for variables but only as primary
+    data source.
+
+    When a template accesses a variable the template does not define, Jinja2
+    looks up the variable in the context, after that the variable is treated
+    as if it was defined in the template.
+
+
+.. _loaders:
+
+Loaders
+-------
+
+Loaders are responsible for loading templates from a resource such as the
+file system.  The environment will keep the compiled modules in memory like
+Python's `sys.modules`.  Unlike `sys.modules` however this cache is limited in
+size by default and templates are automatically reloaded.
+All loaders are subclasses of :class:`BaseLoader`.  If you want to create your
+own loader, subclass :class:`BaseLoader` and override `get_source`.
+
+.. autoclass:: jinja2.BaseLoader
+    :members: get_source, load
+
+Here a list of the builtin loaders Jinja2 provides:
+
+.. autoclass:: jinja2.FileSystemLoader
+
+.. autoclass:: jinja2.PackageLoader
+
+.. autoclass:: jinja2.DictLoader
+
+.. autoclass:: jinja2.FunctionLoader
+
+.. autoclass:: jinja2.PrefixLoader
+
+.. autoclass:: jinja2.ChoiceLoader
+
+
+.. _bytecode-cache:
+
+Bytecode Cache
+--------------
+
+Jinja 2.1 and higher support external bytecode caching.  Bytecode caches make
+it possible to store the generated bytecode on the file system or a different
+location to avoid parsing the templates on first use.
+
+This is especially useful if you have a web application that is initialized on
+the first request and Jinja compiles many templates at once which slows down
+the application.
+
+To use a bytecode cache, instanciate it and pass it to the :class:`Environment`.
+
+.. autoclass:: jinja2.BytecodeCache
+    :members: load_bytecode, dump_bytecode, clear
+
+.. autoclass:: jinja2.bccache.Bucket
+    :members: write_bytecode, load_bytecode, bytecode_from_string,
+              bytecode_to_string, reset
+
+    .. attribute:: environment
+
+        The :class:`Environment` that created the bucket.
+
+    .. attribute:: key
+
+        The unique cache key for this bucket
+
+    .. attribute:: code
+
+        The bytecode if it's loaded, otherwise `None`.
+
+
+Builtin bytecode caches:
+
+.. autoclass:: jinja2.FileSystemBytecodeCache
+
+.. autoclass:: jinja2.MemcachedBytecodeCache
+
+
+Utilities
+---------
+
+These helper functions and classes are useful if you add custom filters or
+functions to a Jinja2 environment.
+
+.. autofunction:: jinja2.environmentfilter
+
+.. autofunction:: jinja2.contextfilter
+
+.. autofunction:: jinja2.evalcontextfilter
+
+.. autofunction:: jinja2.environmentfunction
+
+.. autofunction:: jinja2.contextfunction
+
+.. autofunction:: jinja2.evalcontextfunction
+
+.. function:: escape(s)
+
+    Convert the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in string `s`
+    to HTML-safe sequences.  Use this if you need to display text that might
+    contain such characters in HTML.  This function will not escaped objects
+    that do have an HTML representation such as already escaped data.
+
+    The return value is a :class:`Markup` string.
+
+.. autofunction:: jinja2.clear_caches
+
+.. autofunction:: jinja2.is_undefined
+
+.. autoclass:: jinja2.Markup([string])
+    :members: escape, unescape, striptags
+
+.. admonition:: Note
+
+    The Jinja2 :class:`Markup` class is compatible with at least Pylons and
+    Genshi.  It's expected that more template engines and framework will pick
+    up the `__html__` concept soon.
+
+
+Exceptions
+----------
+
+.. autoexception:: jinja2.TemplateError
+
+.. autoexception:: jinja2.UndefinedError
+
+.. autoexception:: jinja2.TemplateNotFound
+
+.. autoexception:: jinja2.TemplatesNotFound
+
+.. autoexception:: jinja2.TemplateSyntaxError
+
+    .. attribute:: message
+
+        The error message as utf-8 bytestring.
+
+    .. attribute:: lineno
+
+        The line number where the error occurred
+
+    .. attribute:: name
+
+        The load name for the template as unicode string.
+
+    .. attribute:: filename
+
+        The filename that loaded the template as bytestring in the encoding
+        of the file system (most likely utf-8 or mbcs on Windows systems).
+
+    The reason why the filename and error message are bytestrings and not
+    unicode strings is that Python 2.x is not using unicode for exceptions
+    and tracebacks as well as the compiler.  This will change with Python 3.
+
+.. autoexception:: jinja2.TemplateAssertionError
+
+
+.. _writing-filters:
+
+Custom Filters
+--------------
+
+Custom filters are just regular Python functions that take the left side of
+the filter as first argument and the the arguments passed to the filter as
+extra arguments or keyword arguments.
+
+For example in the filter ``{{ 42|myfilter(23) }}`` the function would be
+called with ``myfilter(42, 23)``.  Here for example a simple filter that can
+be applied to datetime objects to format them::
+
+    def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
+        return value.strftime(format)
+
+You can register it on the template environment by updating the
+:attr:`~Environment.filters` dict on the environment::
+
+    environment.filters['datetimeformat'] = datetimeformat
+
+Inside the template it can then be used as follows:
+
+.. sourcecode:: jinja
+
+    written on: {{ article.pub_date|datetimeformat }}
+    publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}
+
+Filters can also be passed the current template context or environment.  This
+is useful if a filter wants to return an undefined value or check the current
+:attr:`~Environment.autoescape` setting.  For this purpose three decorators
+exist: :func:`environmentfilter`, :func:`contextfilter` and
+:func:`evalcontextfilter`.
+
+Here a small example filter that breaks a text into HTML line breaks and
+paragraphs and marks the return value as safe HTML string if autoescaping is
+enabled::
+
+    import re
+    from jinja2 import environmentfilter, Markup, escape
+
+    _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
+
+    @evalcontextfilter
+    def nl2br(eval_ctx, value):
+        result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
+                              for p in _paragraph_re.split(escape(value)))
+        if eval_ctx.autoescape:
+            result = Markup(result)
+        return result
+
+Context filters work the same just that the first argument is the current
+active :class:`Context` rather then the environment.
+
+
+.. _eval-context:
+
+Evaluation Context
+------------------
+
+The evaluation context (short eval context or eval ctx) is a new object
+introducted in Jinja 2.4 that makes it possible to activate and deactivate
+compiled features at runtime.
+
+Currently it is only used to enable and disable the automatic escaping but
+can be used for extensions as well.
+
+In previous Jinja versions filters and functions were marked as
+environment callables in order to check for the autoescape status from the
+environment.  In new versions it's encouraged to check the setting from the
+evaluation context instead.
+
+Previous versions::
+
+    @environmentfilter
+    def filter(env, value):
+        result = do_something(value)
+        if env.autoescape:
+            result = Markup(result)
+        return result
+
+In new versions you can either use a :func:`contextfilter` and access the
+evaluation context from the actual context, or use a
+:func:`evalcontextfilter` which directly passes the evaluation context to
+the function::
+
+    @contextfilter
+    def filter(context, value):
+        result = do_something(value)
+        if context.eval_ctx.autoescape:
+            result = Markup(result)
+        return result
+
+    @evalcontextfilter
+    def filter(eval_ctx, value):
+        result = do_something(value)
+        if eval_ctx.autoescape:
+            result = Markup(result)
+        return result
+
+The evaluation context must not be modified at runtime.  Modifications
+must only happen with a :class:`nodes.EvalContextModifier` and
+:class:`nodes.ScopedEvalContextModifier` from an extension, not on the
+eval context object itself.
+
+.. autoclass:: jinja2.nodes.EvalContext
+
+   .. attribute:: autoescape
+
+      `True` or `False` depending on if autoescaping is active or not.
+
+   .. attribute:: volatile
+
+      `True` if the compiler cannot evaluate some expressions at compile
+      time.  At runtime this should always be `False`.
+
+
+.. _writing-tests:
+
+Custom Tests
+------------
+
+Tests work like filters just that there is no way for a test to get access
+to the environment or context and that they can't be chained.  The return
+value of a test should be `True` or `False`.  The purpose of a test is to
+give the template designers the possibility to perform type and conformability
+checks.
+
+Here a simple test that checks if a variable is a prime number::
+
+    import math
+
+    def is_prime(n):
+        if n == 2:
+            return True
+        for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
+            if n % i == 0:
+                return False
+        return True
+        
+
+You can register it on the template environment by updating the
+:attr:`~Environment.tests` dict on the environment::
+
+    environment.tests['prime'] = is_prime
+
+A template designer can then use the test like this:
+
+.. sourcecode:: jinja
+
+    {% if 42 is prime %}
+        42 is a prime number
+    {% else %}
+        42 is not a prime number
+    {% endif %}
+
+
+.. _global-namespace:
+
+The Global Namespace
+--------------------
+
+Variables stored in the :attr:`Environment.globals` dict are special as they
+are available for imported templates too, even if they are imported without
+context.  This is the place where you can put variables and functions
+that should be available all the time.  Additionally :attr:`Template.globals`
+exist that are variables available to a specific template that are available
+to all :meth:`~Template.render` calls.
+
+
+.. _low-level-api:
+
+Low Level API
+-------------
+
+The low level API exposes functionality that can be useful to understand some
+implementation details, debugging purposes or advanced :ref:`extension
+<jinja-extensions>` techniques.  Unless you know exactly what you are doing we
+don't recommend using any of those.
+
+.. automethod:: Environment.lex
+
+.. automethod:: Environment.parse
+
+.. automethod:: Environment.preprocess
+
+.. automethod:: Template.new_context
+
+.. method:: Template.root_render_func(context)
+
+    This is the low level render function.  It's passed a :class:`Context`
+    that has to be created by :meth:`new_context` of the same template or
+    a compatible template.  This render function is generated by the
+    compiler from the template code and returns a generator that yields
+    unicode strings.
+
+    If an exception in the template code happens the template engine will
+    not rewrite the exception but pass through the original one.  As a
+    matter of fact this function should only be called from within a
+    :meth:`render` / :meth:`generate` / :meth:`stream` call.
+
+.. attribute:: Template.blocks
+
+    A dict of block render functions.  Each of these functions works exactly
+    like the :meth:`root_render_func` with the same limitations.
+
+.. attribute:: Template.is_up_to_date
+
+    This attribute is `False` if there is a newer version of the template
+    available, otherwise `True`.
+
+.. admonition:: Note
+
+    The low-level API is fragile.  Future Jinja2 versions will try not to
+    change it in a backwards incompatible way but modifications in the Jinja2
+    core may shine through.  For example if Jinja2 introduces a new AST node
+    in later versions that may be returned by :meth:`~Environment.parse`.
+
+The Meta API
+------------
+
+.. versionadded:: 2.2
+
+The meta API returns some information about abstract syntax trees that
+could help applications to implement more advanced template concepts.  All
+the functions of the meta API operate on an abstract syntax tree as
+returned by the :meth:`Environment.parse` method.
+
+.. autofunction:: jinja2.meta.find_undeclared_variables
+
+.. autofunction:: jinja2.meta.find_referenced_templates

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/cache_extension.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/cache_extension.py b/ambari-common/src/main/python/jinja2/docs/cache_extension.py
new file mode 100644
index 0000000..8fdefb5
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/cache_extension.py
@@ -0,0 +1,56 @@
+from jinja2 import nodes
+from jinja2.ext import Extension
+
+
+class FragmentCacheExtension(Extension):
+    # a set of names that trigger the extension.
+    tags = set(['cache'])
+
+    def __init__(self, environment):
+        super(FragmentCacheExtension, self).__init__(environment)
+
+        # add the defaults to the environment
+        environment.extend(
+            fragment_cache_prefix='',
+            fragment_cache=None
+        )
+
+    def parse(self, parser):
+        # the first token is the token that started the tag.  In our case
+        # we only listen to ``'cache'`` so this will be a name token with
+        # `cache` as value.  We get the line number so that we can give
+        # that line number to the nodes we create by hand.
+        lineno = parser.stream.next().lineno
+
+        # now we parse a single expression that is used as cache key.
+        args = [parser.parse_expression()]
+
+        # if there is a comma, the user provided a timeout.  If not use
+        # None as second parameter.
+        if parser.stream.skip_if('comma'):
+            args.append(parser.parse_expression())
+        else:
+            args.append(nodes.Const(None))
+
+        # now we parse the body of the cache block up to `endcache` and
+        # drop the needle (which would always be `endcache` in that case)
+        body = parser.parse_statements(['name:endcache'], drop_needle=True)
+
+        # now return a `CallBlock` node that calls our _cache_support
+        # helper method on this extension.
+        return nodes.CallBlock(self.call_method('_cache_support', args),
+                               [], [], body).set_lineno(lineno)
+
+    def _cache_support(self, name, timeout, caller):
+        """Helper callback."""
+        key = self.environment.fragment_cache_prefix + name
+
+        # try to load the block from the cache
+        # if there is no fragment in the cache, render it and store
+        # it in the cache.
+        rv = self.environment.fragment_cache.get(key)
+        if rv is not None:
+            return rv
+        rv = caller()
+        self.environment.fragment_cache.add(key, rv, timeout)
+        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/changelog.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/changelog.rst b/ambari-common/src/main/python/jinja2/docs/changelog.rst
new file mode 100644
index 0000000..9f11484
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/changelog.rst
@@ -0,0 +1,3 @@
+.. module:: jinja2
+
+.. include:: ../CHANGES

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/conf.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/conf.py b/ambari-common/src/main/python/jinja2/docs/conf.py
new file mode 100644
index 0000000..ba90c49
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/conf.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+#
+# Jinja2 documentation build configuration file, created by
+# sphinx-quickstart on Sun Apr 27 21:42:41 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'jinjaext']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'Jinja2'
+copyright = '2008, Armin Ronacher'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '2.0'
+# The full version, including alpha/beta/rc tags.
+release = '2.0'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'jinjaext.JinjaStyle'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'style.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# no modindex
+html_use_modindex = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.
+#html_use_opensearch = False
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Jinja2doc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+latex_paper_size = 'a4'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'Jinja2.tex', 'Jinja2 Documentation', 'Armin Ronacher', 'manual', 'toctree_only'),
+]
+
+# Additional stuff for the LaTeX preamble.
+latex_preamble = '''
+\usepackage{palatino}
+\definecolor{TitleColor}{rgb}{0.7,0,0}
+\definecolor{InnerLinkColor}{rgb}{0.7,0,0}
+\definecolor{OuterLinkColor}{rgb}{0.8,0,0}
+\definecolor{VerbatimColor}{rgb}{0.985,0.985,0.985}
+\definecolor{VerbatimBorderColor}{rgb}{0.8,0.8,0.8}
+'''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+latex_use_modindex = False

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/extensions.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/extensions.rst b/ambari-common/src/main/python/jinja2/docs/extensions.rst
new file mode 100644
index 0000000..c6b6ec9
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/extensions.rst
@@ -0,0 +1,347 @@
+.. _jinja-extensions:
+
+Extensions
+==========
+
+Jinja2 supports extensions that can add extra filters, tests, globals or even
+extend the parser.  The main motivation of extensions is it to move often used
+code into a reusable class like adding support for internationalization.
+
+
+Adding Extensions
+-----------------
+
+Extensions are added to the Jinja2 environment at creation time.  Once the
+environment is created additional extensions cannot be added.  To add an
+extension pass a list of extension classes or import paths to the
+`environment` parameter of the :class:`Environment` constructor.  The following
+example creates a Jinja2 environment with the i18n extension loaded::
+
+    jinja_env = Environment(extensions=['jinja2.ext.i18n'])
+
+
+.. _i18n-extension:
+
+i18n Extension
+--------------
+
+**Import name:** `jinja2.ext.i18n`
+
+Jinja2 currently comes with one extension, the i18n extension.  It can be
+used in combination with `gettext`_ or `babel`_.  If the i18n extension is
+enabled Jinja2 provides a `trans` statement that marks the wrapped string as
+translatable and calls `gettext`.
+
+After enabling dummy `_` function that forwards calls to `gettext` is added
+to the environment globals.  An internationalized application then has to
+provide at least an `gettext` and optoinally a `ngettext` function into the
+namespace.  Either globally or for each rendering.
+
+Environment Methods
+~~~~~~~~~~~~~~~~~~~
+
+After enabling of the extension the environment provides the following
+additional methods:
+
+.. method:: jinja2.Environment.install_gettext_translations(translations, newstyle=False)
+
+    Installs a translation globally for that environment.  The tranlations
+    object provided must implement at least `ugettext` and `ungettext`.
+    The `gettext.NullTranslations` and `gettext.GNUTranslations` classes
+    as well as `Babel`_\s `Translations` class are supported.
+
+    .. versionchanged:: 2.5 newstyle gettext added
+
+.. method:: jinja2.Environment.install_null_translations(newstyle=False)
+
+    Install dummy gettext functions.  This is useful if you want to prepare
+    the application for internationalization but don't want to implement the
+    full internationalization system yet.
+
+    .. versionchanged:: 2.5 newstyle gettext added
+
+.. method:: jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False)
+
+    Installs the given `gettext` and `ngettext` callables into the
+    environment as globals.  They are supposed to behave exactly like the
+    standard library's :func:`gettext.ugettext` and
+    :func:`gettext.ungettext` functions.
+
+    If `newstyle` is activated, the callables are wrapped to work like
+    newstyle callables.  See :ref:`newstyle-gettext` for more information.
+
+    .. versionadded:: 2.5
+
+.. method:: jinja2.Environment.uninstall_gettext_translations()
+
+    Uninstall the translations again.
+
+.. method:: jinja2.Environment.extract_translations(source)
+
+    Extract localizable strings from the given template node or source.
+
+    For every string found this function yields a ``(lineno, function,
+    message)`` tuple, where:
+
+    * `lineno` is the number of the line on which the string was found,
+    * `function` is the name of the `gettext` function used (if the
+      string was extracted from embedded Python code), and
+    *  `message` is the string itself (a `unicode` object, or a tuple
+       of `unicode` objects for functions with multiple string arguments).
+
+    If `Babel`_ is installed :ref:`the babel integration <babel-integration>`
+    can be used to extract strings for babel.
+
+For a web application that is available in multiple languages but gives all
+the users the same language (for example a multilingual forum software
+installed for a French community) may load the translations once and add the
+translation methods to the environment at environment generation time::
+
+    translations = get_gettext_translations()
+    env = Environment(extensions=['jinja2.ext.i18n'])
+    env.install_gettext_translations(translations)
+
+The `get_gettext_translations` function would return the translator for the
+current configuration.  (For example by using `gettext.find`)
+
+The usage of the `i18n` extension for template designers is covered as part
+:ref:`of the template documentation <i18n-in-templates>`.
+
+.. _gettext: http://docs.python.org/dev/library/gettext
+.. _Babel: http://babel.edgewall.org/
+
+.. _newstyle-gettext:
+
+Newstyle Gettext
+~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.5
+
+Starting with version 2.5 you can use newstyle gettext calls.  These are
+inspired by trac's internal gettext functions and are fully supported by
+the babel extraction tool.  They might not work as expected by other
+extraction tools in case you are not using Babel's.
+
+What's the big difference between standard and newstyle gettext calls?  In
+general they are less to type and less error prone.  Also if they are used
+in an autoescaping environment they better support automatic escaping.
+Here some common differences between old and new calls:
+
+standard gettext:
+
+.. sourcecode:: html+jinja
+
+    {{ gettext('Hello World!') }}
+    {{ gettext('Hello %(name)s!')|format(name='World') }}
+    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count)|format(
+        num=apples|count
+    )}}
+
+newstyle gettext looks like this instead:
+
+.. sourcecode:: html+jinja
+
+    {{ gettext('Hello World!') }}
+    {{ gettext('Hello %(name)s!', name='World') }}
+    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
+
+The advantages of newstyle gettext is that you have less to type and that
+named placeholders become mandatory.  The latter sounds like a
+disadvantage but solves a lot of troubles translators are often facing
+when they are unable to switch the positions of two placeholder.  With
+newstyle gettext, all format strings look the same.
+
+Furthermore with newstyle gettext, string formatting is also used if no
+placeholders are used which makes all strings behave exactly the same.
+Last but not least are newstyle gettext calls able to properly mark
+strings for autoescaping which solves lots of escaping related issues many
+templates are experiencing over time when using autoescaping.
+
+Expression Statement
+--------------------
+
+**Import name:** `jinja2.ext.do`
+
+The "do" aka expression-statement extension adds a simple `do` tag to the
+template engine that works like a variable expression but ignores the
+return value.
+
+.. _loopcontrols-extension:
+
+Loop Controls
+-------------
+
+**Import name:** `jinja2.ext.loopcontrols`
+
+This extension adds support for `break` and `continue` in loops.  After
+enabling Jinja2 provides those two keywords which work exactly like in
+Python.
+
+.. _with-extension:
+
+With Statement
+--------------
+
+**Import name:** `jinja2.ext.with_`
+
+.. versionadded:: 2.3
+
+This extension adds support for the with keyword.  Using this keyword it
+is possible to enforce a nested scope in a template.  Variables can be
+declared directly in the opening block of the with statement or using a
+standard `set` statement directly within.
+
+.. _autoescape-extension:
+
+Autoescape Extension
+--------------------
+
+**Import name:** `jinja2.ext.autoescape`
+
+.. versionadded:: 2.4
+
+The autoescape extension allows you to toggle the autoescape feature from
+within the template.  If the environment's :attr:`~Environment.autoescape`
+setting is set to `False` it can be activated, if it's `True` it can be
+deactivated.  The setting overriding is scoped.
+
+
+.. _writing-extensions:
+
+Writing Extensions
+------------------
+
+.. module:: jinja2.ext
+
+By writing extensions you can add custom tags to Jinja2.  This is a non trival
+task and usually not needed as the default tags and expressions cover all
+common use cases.  The i18n extension is a good example of why extensions are
+useful, another one would be fragment caching.
+
+When writing extensions you have to keep in mind that you are working with the
+Jinja2 template compiler which does not validate the node tree you are possing
+to it.  If the AST is malformed you will get all kinds of compiler or runtime
+errors that are horrible to debug.  Always make sure you are using the nodes
+you create correctly.  The API documentation below shows which nodes exist and
+how to use them.
+
+Example Extension
+~~~~~~~~~~~~~~~~~
+
+The following example implements a `cache` tag for Jinja2 by using the
+`Werkzeug`_ caching contrib module:
+
+.. literalinclude:: cache_extension.py
+    :language: python
+
+And here is how you use it in an environment::
+
+    from jinja2 import Environment
+    from werkzeug.contrib.cache import SimpleCache
+
+    env = Environment(extensions=[FragmentCacheExtension])
+    env.fragment_cache = SimpleCache()
+
+Inside the template it's then possible to mark blocks as cacheable.  The
+following example caches a sidebar for 300 seconds:
+
+.. sourcecode:: html+jinja
+
+    {% cache 'sidebar', 300 %}
+    <div class="sidebar">
+        ...
+    </div>
+    {% endcache %}
+
+.. _Werkzeug: http://werkzeug.pocoo.org/
+
+Extension API
+~~~~~~~~~~~~~
+
+Extensions always have to extend the :class:`jinja2.ext.Extension` class:
+
+.. autoclass:: Extension
+    :members: preprocess, filter_stream, parse, attr, call_method
+
+    .. attribute:: identifier
+
+        The identifier of the extension.  This is always the true import name
+        of the extension class and must not be changed.
+
+    .. attribute:: tags
+
+        If the extension implements custom tags this is a set of tag names
+        the extension is listening for.
+
+Parser API
+~~~~~~~~~~
+
+The parser passed to :meth:`Extension.parse` provides ways to parse
+expressions of different types.  The following methods may be used by
+extensions:
+
+.. autoclass:: jinja2.parser.Parser
+    :members: parse_expression, parse_tuple, parse_assign_target,
+              parse_statements, free_identifier, fail
+
+    .. attribute:: filename
+
+        The filename of the template the parser processes.  This is **not**
+        the load name of the template.  For the load name see :attr:`name`.
+        For templates that were not loaded form the file system this is
+        `None`.
+
+    .. attribute:: name
+
+        The load name of the template.
+
+    .. attribute:: stream
+
+        The current :class:`~jinja2.lexer.TokenStream`
+
+.. autoclass:: jinja2.lexer.TokenStream
+   :members: push, look, eos, skip, next, next_if, skip_if, expect
+
+   .. attribute:: current
+
+        The current :class:`~jinja2.lexer.Token`.
+
+.. autoclass:: jinja2.lexer.Token
+    :members: test, test_any
+
+    .. attribute:: lineno
+
+        The line number of the token
+
+    .. attribute:: type
+
+        The type of the token.  This string is interned so you may compare
+        it with arbitrary strings using the `is` operator.
+
+    .. attribute:: value
+
+        The value of the token.
+
+There is also a utility function in the lexer module that can count newline
+characters in strings:
+
+.. autofunction:: jinja2.lexer.count_newlines
+
+AST
+~~~
+
+The AST (Abstract Syntax Tree) is used to represent a template after parsing.
+It's build of nodes that the compiler then converts into executable Python
+code objects.  Extensions that provide custom statements can return nodes to
+execute custom Python code.
+
+The list below describes all nodes that are currently available.  The AST may
+change between Jinja2 versions but will stay backwards compatible.
+
+For more information have a look at the repr of :meth:`jinja2.Environment.parse`.
+
+.. module:: jinja2.nodes
+
+.. jinjanodes::
+
+.. autoexception:: Impossible

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/faq.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/faq.rst b/ambari-common/src/main/python/jinja2/docs/faq.rst
new file mode 100644
index 0000000..89186b1
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/faq.rst
@@ -0,0 +1,191 @@
+Frequently Asked Questions
+==========================
+
+This page answers some of the often asked questions about Jinja.
+
+.. highlight:: html+jinja
+
+Why is it called Jinja?
+-----------------------
+
+The name Jinja was chosen because it's the name of a Japanese temple and
+temple and template share a similar pronunciation.  It is not named after
+the capital city of Uganda.
+
+How fast is it?
+---------------
+
+We really hate benchmarks especially since they don't reflect much.  The
+performance of a template depends on many factors and you would have to
+benchmark different engines in different situations.  The benchmarks from the
+testsuite show that Jinja2 has a similar performance to `Mako`_ and is between
+10 and 20 times faster than Django's template engine or Genshi.  These numbers
+should be taken with tons of salt as the benchmarks that took these numbers
+only test a few performance related situations such as looping.  Generally
+speaking the performance of a template engine doesn't matter much as the
+usual bottleneck in a web application is either the database or the application
+code.
+
+.. _Mako: http://www.makotemplates.org/
+
+How Compatible is Jinja2 with Django?
+-------------------------------------
+
+The default syntax of Jinja2 matches Django syntax in many ways.  However
+this similarity doesn't mean that you can use a Django template unmodified
+in Jinja2.  For example filter arguments use a function call syntax rather
+than a colon to separate filter name and arguments.  Additionally the
+extension interface in Jinja is fundamentally different from the Django one
+which means that your custom tags won't work any longer.
+
+Generally speaking you will use much less custom extensions as the Jinja
+template system allows you to use a certain subset of Python expressions
+which can replace most Django extensions.  For example instead of using
+something like this::
+
+    {% load comments %}
+    {% get_latest_comments 10 as latest_comments %}
+    {% for comment in latest_comments %}
+        ...
+    {% endfor %}
+
+You will most likely provide an object with attributes to retrieve
+comments from the database::
+
+    {% for comment in models.comments.latest(10) %}
+        ...
+    {% endfor %}
+
+Or directly provide the model for quick testing::
+
+    {% for comment in Comment.objects.order_by('-pub_date')[:10] %}
+        ...
+    {% endfor %}
+
+Please keep in mind that even though you may put such things into templates
+it still isn't a good idea.  Queries should go into the view code and not
+the template!
+
+Isn't it a terrible idea to put Logic into Templates?
+-----------------------------------------------------
+
+Without a doubt you should try to remove as much logic from templates as
+possible.  But templates without any logic mean that you have to do all
+the processing in the code which is boring and stupid.  A template engine
+that does that is shipped with Python and called `string.Template`.  Comes
+without loops and if conditions and is by far the fastest template engine
+you can get for Python.
+
+So some amount of logic is required in templates to keep everyone happy.
+And Jinja leaves it pretty much to you how much logic you want to put into
+templates.  There are some restrictions in what you can do and what not.
+
+Jinja2 neither allows you to put arbitrary Python code into templates nor
+does it allow all Python expressions.  The operators are limited to the
+most common ones and more advanced expressions such as list comprehensions
+and generator expressions are not supported.  This keeps the template engine
+easier to maintain and templates more readable.
+
+Why is Autoescaping not the Default?
+------------------------------------
+
+There are multiple reasons why automatic escaping is not the default mode
+and also not the recommended one.  While automatic escaping of variables
+means that you will less likely have an XSS problem it also causes a huge
+amount of extra processing in the template engine which can cause serious
+performance problems.  As Python doesn't provide a way to mark strings as
+unsafe Jinja has to hack around that limitation by providing a custom
+string class (the :class:`Markup` string) that safely interacts with safe
+and unsafe strings.
+
+With explicit escaping however the template engine doesn't have to perform
+any safety checks on variables.  Also a human knows not to escape integers
+or strings that may never contain characters one has to escape or already
+HTML markup.  For example when iterating over a list over a table of
+integers and floats for a table of statistics the template designer can
+omit the escaping because he knows that integers or floats don't contain
+any unsafe parameters.
+
+Additionally Jinja2 is a general purpose template engine and not only used
+for HTML/XML generation.  For example you may generate LaTeX, emails,
+CSS, JavaScript, or configuration files.
+
+Why is the Context immutable?
+-----------------------------
+
+When writing a :func:`contextfunction` or something similar you may have
+noticed that the context tries to stop you from modifying it.  If you have
+managed to modify the context by using an internal context API you may
+have noticed that changes in the context don't seem to be visible in the
+template.  The reason for this is that Jinja uses the context only as
+primary data source for template variables for performance reasons.
+
+If you want to modify the context write a function that returns a variable
+instead that one can assign to a variable by using set::
+
+    {% set comments = get_latest_comments() %}
+
+What is the speedups module and why is it missing?
+--------------------------------------------------
+
+To achieve a good performance with automatic escaping enabled, the escaping
+function was also implemented in pure C in older Jinja2 releases and used if
+Jinja2 was installed with the speedups module.
+
+Because this feature itself is very useful for non-template engines as
+well it was moved into a separate project on PyPI called `MarkupSafe`_.
+
+Jinja2 no longer ships with a C implementation of it but only the pure
+Python implementation.  It will however check if MarkupSafe is available
+and installed, and if it is, use the Markup class from MarkupSafe.
+
+So if you want the speedups, just import MarkupSafe.
+
+.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
+
+My tracebacks look weird.  What's happening?
+--------------------------------------------
+
+If the debugsupport module is not compiled and you are using a Python
+installation without ctypes (Python 2.4 without ctypes, Jython or Google's
+AppEngine) Jinja2 is unable to provide correct debugging information and
+the traceback may be incomplete.  There is currently no good workaround
+for Jython or the AppEngine as ctypes is unavailable there and it's not
+possible to use the debugsupport extension.
+
+Why is there no Python 2.3 support?
+-----------------------------------
+
+Python 2.3 is missing a lot of features that are used heavily in Jinja2.  This
+decision was made as with the upcoming Python 2.6 and 3.0 versions it becomes
+harder to maintain the code for older Python versions.  If you really need
+Python 2.3 support you either have to use `Jinja 1`_ or other templating
+engines that still support 2.3.
+
+My Macros are overriden by something
+------------------------------------
+
+In some situations the Jinja scoping appears arbitrary:
+
+layout.tmpl:
+
+.. sourcecode:: jinja
+
+    {% macro foo() %}LAYOUT{% endmacro %}
+    {% block body %}{% endblock %}
+
+child.tmpl:
+
+.. sourcecode:: jinja
+
+    {% extends 'layout.tmpl' %}
+    {% macro foo() %}CHILD{% endmacro %}
+    {% block body %}{{ foo() }}{% endblock %}
+
+This will print ``LAYOUT`` in Jinja2.  This is a side effect of having
+the parent template evaluated after the child one.  This allows child
+templates passing information to the parent template.  To avoid this
+issue rename the macro or variable in the parent template to have an
+uncommon prefix.
+
+.. _Jinja 1: http://jinja.pocoo.org/1/

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/index.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/index.rst b/ambari-common/src/main/python/jinja2/docs/index.rst
new file mode 100644
index 0000000..27bee23
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/index.rst
@@ -0,0 +1,27 @@
+Jinja2 Documentation
+====================
+
+This is the documentation for the Jinja2 general purpose templating language.
+Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
+fast and secure.
+
+.. toctree::
+   :maxdepth: 2
+
+   intro
+   api
+   sandbox
+   templates
+   extensions
+   integration
+   switching
+   tricks
+
+   faq
+   changelog
+
+If you can't find the information you're looking for, have a look at the
+index of try to find it using the search function:
+
+* :ref:`genindex`
+* :ref:`search`

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/integration.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/integration.rst b/ambari-common/src/main/python/jinja2/docs/integration.rst
new file mode 100644
index 0000000..1875711
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/integration.rst
@@ -0,0 +1,88 @@
+Integration
+===========
+
+Jinja2 provides some code for integration into other tools such as frameworks,
+the `Babel`_ library or your favourite editor for fancy code highlighting.
+This is a brief description of whats included.
+
+.. _babel-integration:
+
+Babel Integration
+-----------------
+
+Jinja provides support for extracting gettext messages from templates via a
+`Babel`_ extractor entry point called `jinja2.ext.babel_extract`.  The Babel
+support is implemented as part of the :ref:`i18n-extension` extension.
+
+Gettext messages extracted from both `trans` tags and code expressions.
+
+To extract gettext messages from templates, the project needs a Jinja2 section
+in its Babel extraction method `mapping file`_:
+
+.. sourcecode:: ini
+
+    [jinja2: **/templates/**.html]
+    encoding = utf-8
+
+The syntax related options of the :class:`Environment` are also available as
+configuration values in the mapping file.  For example to tell the extraction
+that templates use ``%`` as `line_statement_prefix` you can use this code:
+
+.. sourcecode:: ini
+
+    [jinja2: **/templates/**.html]
+    encoding = utf-8
+    line_statement_prefix = %
+
+:ref:`jinja-extensions` may also be defined by passing a comma separated list
+of import paths as `extensions` value.  The i18n extension is added
+automatically.
+
+.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
+
+Pylons
+------
+
+With `Pylons`_ 0.9.7 onwards it's incredible easy to integrate Jinja into a
+Pylons powered application.
+
+The template engine is configured in `config/environment.py`.  The configuration
+for Jinja2 looks something like that::
+
+    from jinja2 import Environment, PackageLoader
+    config['pylons.app_globals'].jinja_env = Environment(
+        loader=PackageLoader('yourapplication', 'templates')
+    )
+
+After that you can render Jinja templates by using the `render_jinja` function
+from the `pylons.templating` module.
+
+Additionally it's a good idea to set the Pylons' `c` object into strict mode.
+Per default any attribute to not existing attributes on the `c` object return
+an empty string and not an undefined object.  To change this just use this
+snippet and add it into your `config/environment.py`::
+
+    config['pylons.strict_c'] = True
+
+.. _Pylons: http://www.pylonshq.com/
+
+TextMate
+--------
+
+Inside the `ext` folder of Jinja2 there is a bundle for TextMate that supports
+syntax highlighting for Jinja1 and Jinja2 for text based templates as well as
+HTML.  It also contains a few often used snippets.
+
+Vim
+---
+
+A syntax plugin for `Vim`_ exists in the Vim-scripts directory as well as the
+ext folder of Jinja2.  `The script <http://www.vim.org/scripts/script.php?script_id=1856>`_
+supports Jinja1 and Jinja2.  Once installed two file types are available `jinja`
+and `htmljinja`.  The first one for text based templates, the latter for HTML
+templates.
+
+Copy the files into your `syntax` folder.
+
+.. _Babel: http://babel.edgewall.org/
+.. _Vim: http://www.vim.org/

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/intro.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/intro.rst b/ambari-common/src/main/python/jinja2/docs/intro.rst
new file mode 100644
index 0000000..0800615
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/intro.rst
@@ -0,0 +1,168 @@
+Introduction
+============
+
+This is the documentation for the Jinja2 general purpose templating language.
+Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
+fast and secure.
+
+If you have any exposure to other text-based template languages, such as Smarty or
+Django, you should feel right at home with Jinja2.  It's both designer and
+developer friendly by sticking to Python's principles and adding functionality
+useful for templating environments.
+
+The key-features are...
+
+-   ... **configurable syntax**.  If you are generating LaTeX or other formats
+    with Jinja2 you can change the delimiters to something that integrates better
+    into the LaTeX markup.
+
+-   ... **fast**.  While performance is not the primarily target of Jinja2 it's
+    surprisingly fast.  The overhead compared to regular Python code was reduced
+    to the very minimum.
+
+-   ... **easy to debug**.  Jinja2 integrates directly into the python traceback
+    system which allows you to debug Jinja2 templates with regular python
+    debugging helpers.
+
+-   ... **secure**.  It's possible to evaluate untrusted template code if the
+    optional sandbox is enabled.  This allows Jinja2 to be used as templating
+    language for applications where users may modify the template design.
+
+
+Prerequisites
+-------------
+
+Jinja2 needs at least **Python 2.4** to run.  Additionally a working C-compiler
+that can create python extensions should be installed for the debugger if you
+are using Python 2.4.
+
+If you don't have a working C-compiler and you are trying to install the source
+release with the debugsupport you will get a compiler error.
+
+.. _ctypes: http://python.net/crew/theller/ctypes/
+
+
+Installation
+------------
+
+You have multiple ways to install Jinja2.  If you are unsure what to do, go
+with the Python egg or tarball.
+
+As a Python egg (via easy_install)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can install the most recent Jinja2 version using `easy_install`_ or `pip`_::
+
+    easy_install Jinja2
+    pip install Jinja2
+
+This will install a Jinja2 egg in your Python installation's site-packages
+directory.
+
+(If you are installing from the windows command line omit the `sudo` and make
+sure to run the command as user with administrator rights)
+
+From the tarball release
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1.  Download the most recent tarball from the `download page`_
+2.  Unpack the tarball
+3.  ``sudo python setup.py install``
+
+Note that you either have to have setuptools or `distribute`_ installed,
+the latter is preferred.
+
+This will install Jinja2 into your Python installation's site-packages directory.
+
+.. _distribute: http://pypi.python.org/pypi/distribute
+
+Installing the development version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1.  Install `git`_
+2.  ``git clone git://github.com/mitsuhiko/jinja2.git``
+3.  ``cd jinja2``
+4.  ``ln -s jinja2 /usr/lib/python2.X/site-packages``
+
+As an alternative to steps 4 you can also do ``python setup.py develop``
+which will install the package via distribute in development mode.  This also
+has the advantage that the C extensions are compiled.
+
+.. _download page: http://pypi.python.org/pypi/Jinja2
+.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
+.. _pip: http://pypi.python.org/pypi/pip
+.. _git: http://git-scm.org/
+
+
+More Speed with MarkupSafe
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As of version 2.5.1 Jinja2 will check for an installed `MarkupSafe`_
+module.  If it can find it, it will use the Markup class of that module
+instead of the one that comes with Jinja2.  `MarkupSafe` replaces the
+older speedups module that came with Jinja2 and has the advantage that is
+has a better setup script and will automatically attempt to install the C
+version and nicely fall back to a pure Python implementation if that is
+not possible.
+
+The C implementation of MarkupSafe is much faster and recommended when
+using Jinja2 with autoescaping.
+
+.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
+
+
+Enable the debug support Module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default Jinja2 will not compile the debug support module.  Enabling this
+will fail if you don't have the Python headers or a working compiler.  This
+is often the case if you are installing Jinja2 from a windows machine.
+
+Because the debug support is only necessary for Python 2.4 you will not
+have to do this unless you run 2.4::
+
+    sudo python setup.py --with-debugsupport install
+
+
+Basic API Usage
+---------------
+
+This section gives you a brief introduction to the Python API for Jinja2
+templates.
+
+The most basic way to create a template and render it is through
+:class:`~jinja2.Template`.  This however is not the recommended way to
+work with it if your templates are not loaded from strings but the file
+system or another data source:
+
+>>> from jinja2 import Template
+>>> template = Template('Hello {{ name }}!')
+>>> template.render(name='John Doe')
+u'Hello John Doe!'
+
+By creating an instance of :class:`~jinja2.Template` you get back a new template
+object that provides a method called :meth:`~jinja2.Template.render` which when
+called with a dict or keyword arguments expands the template.  The dict
+or keywords arguments passed to the template are the so-called "context"
+of the template.
+
+What you can see here is that Jinja2 is using unicode internally and the
+return value is an unicode string.  So make sure that your application is
+indeed using unicode internally.
+
+
+Experimental Python 3 Support
+-----------------------------
+
+Jinja 2.3 brings experimental support for Python 3.  It means that all
+unittests pass on the new version, but there might still be small bugs in
+there and behavior might be inconsistent.  If you notice any bugs, please
+provide feedback in the `Jinja bug tracker`_.
+
+Also please keep in mind that the documentation is written with Python 2
+in mind, you will have to adapt the shown code examples to Python 3 syntax
+for yourself.
+
+
+.. _Jinja bug tracker: http://github.com/mitsuhiko/jinja2/issues

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/jinjaext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/jinjaext.py b/ambari-common/src/main/python/jinja2/docs/jinjaext.py
new file mode 100644
index 0000000..66f4ba1
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/jinjaext.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+"""
+    Jinja Documentation Extensions
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Support for automatically documenting filters and tests.
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: BSD.
+"""
+import os
+import re
+import inspect
+import jinja2
+from itertools import islice
+from types import BuiltinFunctionType
+from docutils import nodes
+from docutils.statemachine import ViewList
+from sphinx.ext.autodoc import prepare_docstring
+from sphinx.application import TemplateBridge
+from pygments.style import Style
+from pygments.token import Keyword, Name, Comment, String, Error, \
+     Number, Operator, Generic
+from jinja2 import Environment, FileSystemLoader
+
+
+def parse_rst(state, content_offset, doc):
+    node = nodes.section()
+    # hack around title style bookkeeping
+    surrounding_title_styles = state.memo.title_styles
+    surrounding_section_level = state.memo.section_level
+    state.memo.title_styles = []
+    state.memo.section_level = 0
+    state.nested_parse(doc, content_offset, node, match_titles=1)
+    state.memo.title_styles = surrounding_title_styles
+    state.memo.section_level = surrounding_section_level
+    return node.children
+
+
+class JinjaStyle(Style):
+    title = 'Jinja Style'
+    default_style = ""
+    styles = {
+        Comment:                    'italic #aaaaaa',
+        Comment.Preproc:            'noitalic #B11414',
+        Comment.Special:            'italic #505050',
+
+        Keyword:                    'bold #B80000',
+        Keyword.Type:               '#808080',
+
+        Operator.Word:              'bold #B80000',
+
+        Name.Builtin:               '#333333',
+        Name.Function:              '#333333',
+        Name.Class:                 'bold #333333',
+        Name.Namespace:             'bold #333333',
+        Name.Entity:                'bold #363636',
+        Name.Attribute:             '#686868',
+        Name.Tag:                   'bold #686868',
+        Name.Decorator:             '#686868',
+
+        String:                     '#AA891C',
+        Number:                     '#444444',
+
+        Generic.Heading:            'bold #000080',
+        Generic.Subheading:         'bold #800080',
+        Generic.Deleted:            '#aa0000',
+        Generic.Inserted:           '#00aa00',
+        Generic.Error:              '#aa0000',
+        Generic.Emph:               'italic',
+        Generic.Strong:             'bold',
+        Generic.Prompt:             '#555555',
+        Generic.Output:             '#888888',
+        Generic.Traceback:          '#aa0000',
+
+        Error:                      '#F00 bg:#FAA'
+    }
+
+
+_sig_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))')
+
+
+def format_function(name, aliases, func):
+    lines = inspect.getdoc(func).splitlines()
+    signature = '()'
+    if isinstance(func, BuiltinFunctionType):
+        match = _sig_re.match(lines[0])
+        if match is not None:
+            del lines[:1 + bool(lines and not lines[0])]
+            signature = match.group(1)
+    else:
+        try:
+            argspec = inspect.getargspec(func)
+            if getattr(func, 'environmentfilter', False) or \
+               getattr(func, 'contextfilter', False):
+                del argspec[0][0]
+            signature = inspect.formatargspec(*argspec)
+        except:
+            pass
+    result = ['.. function:: %s%s' % (name, signature), '']
+    result.extend('    ' + line for line in lines)
+    if aliases:
+        result.extend(('', '    :aliases: %s' % ', '.join(
+                      '``%s``' % x for x in sorted(aliases))))
+    return result
+
+
+def dump_functions(mapping):
+    def directive(dirname, arguments, options, content, lineno,
+                      content_offset, block_text, state, state_machine):
+        reverse_mapping = {}
+        for name, func in mapping.iteritems():
+            reverse_mapping.setdefault(func, []).append(name)
+        filters = []
+        for func, names in reverse_mapping.iteritems():
+            aliases = sorted(names, key=lambda x: len(x))
+            name = aliases.pop()
+            filters.append((name, aliases, func))
+        filters.sort()
+
+        result = ViewList()
+        for name, aliases, func in filters:
+            for item in format_function(name, aliases, func):
+                result.append(item, '<jinjaext>')
+
+        node = nodes.paragraph()
+        state.nested_parse(result, content_offset, node)
+        return node.children
+    return directive
+
+
+from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS
+jinja_filters = dump_functions(DEFAULT_FILTERS)
+jinja_tests = dump_functions(DEFAULT_TESTS)
+
+
+def jinja_nodes(dirname, arguments, options, content, lineno,
+                content_offset, block_text, state, state_machine):
+    from jinja2.nodes import Node
+    doc = ViewList()
+    def walk(node, indent):
+        p = ' ' * indent
+        sig = ', '.join(node.fields)
+        doc.append(p + '.. autoclass:: %s(%s)' % (node.__name__, sig), '')
+        if node.abstract:
+            members = []
+            for key, name in node.__dict__.iteritems():
+                if not key.startswith('_') and \
+                   not hasattr(node.__base__, key) and callable(name):
+                    members.append(key)
+            if members:
+                members.sort()
+                doc.append('%s :members: %s' % (p, ', '.join(members)), '')
+        if node.__base__ != object:
+            doc.append('', '')
+            doc.append('%s :Node type: :class:`%s`' %
+                       (p, node.__base__.__name__), '')
+        doc.append('', '')
+        children = node.__subclasses__()
+        children.sort(key=lambda x: x.__name__.lower())
+        for child in children:
+            walk(child, indent)
+    walk(Node, 0)
+    return parse_rst(state, content_offset, doc)
+
+
+def inject_toc(app, doctree, docname):
+    titleiter = iter(doctree.traverse(nodes.title))
+    try:
+        # skip first title, we are not interested in that one
+        titleiter.next()
+        title = titleiter.next()
+        # and check if there is at least another title
+        titleiter.next()
+    except StopIteration:
+        return
+    tocnode = nodes.section('')
+    tocnode['classes'].append('toc')
+    toctitle = nodes.section('')
+    toctitle['classes'].append('toctitle')
+    toctitle.append(nodes.title(text='Table Of Contents'))
+    tocnode.append(toctitle)
+    tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1]
+    title.parent.insert(title.parent.children.index(title), tocnode)
+
+
+def setup(app):
+    app.add_directive('jinjafilters', jinja_filters, 0, (0, 0, 0))
+    app.add_directive('jinjatests', jinja_tests, 0, (0, 0, 0))
+    app.add_directive('jinjanodes', jinja_nodes, 0, (0, 0, 0))
+    # uncomment for inline toc.  links are broken unfortunately
+    ##app.connect('doctree-resolved', inject_toc)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/sandbox.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/sandbox.rst b/ambari-common/src/main/python/jinja2/docs/sandbox.rst
new file mode 100644
index 0000000..bb0ca9f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/sandbox.rst
@@ -0,0 +1,46 @@
+Sandbox
+=======
+
+The Jinja2 sandbox can be used to evaluate untrusted code.  Access to unsafe
+attributes and methods is prohibited.
+
+Assuming `env` is a :class:`SandboxedEnvironment` in the default configuration
+the following piece of code shows how it works:
+
+>>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
+u''
+>>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
+Traceback (most recent call last):
+  ...
+SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
+
+
+.. module:: jinja2.sandbox
+
+.. autoclass:: SandboxedEnvironment([options])
+    :members: is_safe_attribute, is_safe_callable
+
+.. autoclass:: ImmutableSandboxedEnvironment([options])
+
+.. autoexception:: SecurityError
+
+.. autofunction:: unsafe
+
+.. autofunction:: is_internal_attribute
+
+.. autofunction:: modifies_known_mutable
+
+.. admonition:: Note
+
+    The Jinja2 sandbox alone is no solution for perfect security.  Especially
+    for web applications you have to keep in mind that users may create
+    templates with arbitrary HTML in so it's crucial to ensure that (if you
+    are running multiple users on the same server) they can't harm each other
+    via JavaScript insertions and much more.
+
+    Also the sandbox is only as good as the configuration.  We stronly
+    recommend only passing non-shared resources to the template and use
+    some sort of whitelisting for attributes.
+
+    Also keep in mind that templates may raise runtime or compile time errors,
+    so make sure to catch them.

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/switching.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/switching.rst b/ambari-common/src/main/python/jinja2/docs/switching.rst
new file mode 100644
index 0000000..ba3cfb1
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/switching.rst
@@ -0,0 +1,242 @@
+Switching from other Template Engines
+=====================================
+
+.. highlight:: html+jinja
+
+If you have used a different template engine in the past and want to swtich
+to Jinja2 here is a small guide that shows the basic syntatic and semantic
+changes between some common, similar text template engines for Python.
+
+Jinja1
+------
+
+Jinja2 is mostly compatible with Jinja1 in terms of API usage and template
+syntax.  The differences between Jinja1 and 2 are explained in the following
+list.
+
+API
+~~~
+
+Loaders
+    Jinja2 uses a different loader API.  Because the internal representation
+    of templates changed there is no longer support for external caching
+    systems such as memcached.  The memory consumed by templates is comparable
+    with regular Python modules now and external caching doesn't give any
+    advantage.  If you have used a custom loader in the past have a look at
+    the new :ref:`loader API <loaders>`.
+
+Loading templates from strings
+    In the past it was possible to generate templates from a string with the
+    default environment configuration by using `jinja.from_string`.  Jinja2
+    provides a :class:`Template` class that can be used to do the same, but
+    with optional additional configuration.
+
+Automatic unicode conversion
+    Jinja1 performed automatic conversion of bytestrings in a given encoding
+    into unicode objects.  This conversion is no longer implemented as it
+    was inconsistent as most libraries are using the regular Python ASCII
+    bytestring to Unicode conversion.  An application powered by Jinja2
+    *has to* use unicode internally everywhere or make sure that Jinja2 only
+    gets unicode strings passed.
+
+i18n
+    Jinja1 used custom translators for internationalization.  i18n is now
+    available as Jinja2 extension and uses a simpler, more gettext friendly
+    interface and has support for babel.  For more details see
+    :ref:`i18n-extension`.
+
+Internal methods
+    Jinja1 exposed a few internal methods on the environment object such
+    as `call_function`, `get_attribute` and others.  While they were marked
+    as being an internal method it was possible to override them.  Jinja2
+    doesn't have equivalent methods.
+
+Sandbox
+    Jinja1 was running sandbox mode by default.  Few applications actually
+    used that feature so it became optional in Jinja2.  For more details
+    about the sandboxed execution see :class:`SandboxedEnvironment`.
+
+Context
+    Jinja1 had a stacked context as storage for variables passed to the
+    environment.  In Jinja2 a similar object exists but it doesn't allow
+    modifications nor is it a singleton.  As inheritance is dynamic now
+    multiple context objects may exist during template evaluation.
+
+Filters and Tests
+    Filters and tests are regular functions now.  It's no longer necessary
+    and allowed to use factory functions.
+
+
+Templates
+~~~~~~~~~
+
+Jinja2 has mostly the same syntax as Jinja1.  What's different is that
+macros require parentheses around the argument list now.
+
+Additionally Jinja2 allows dynamic inheritance now and dynamic includes.
+The old helper function `rendertemplate` is gone now, `include` can be used
+instead.  Includes no longer import macros and variable assignments, for
+that the new `import` tag is used.  This concept is explained in the
+:ref:`import` documentation.
+
+Another small change happened in the `for`-tag.  The special loop variable
+doesn't have a `parent` attribute, instead you have to alias the loop
+yourself.  See :ref:`accessing-the-parent-loop` for more details.
+
+
+Django
+------
+
+If you have previously worked with Django templates, you should find
+Jinja2 very familiar.  In fact, most of the syntax elements look and
+work the same.
+
+However, Jinja2 provides some more syntax elements covered in the
+documentation and some work a bit different.
+
+This section covers the template changes.  As the API is fundamentally
+different we won't cover it here.
+
+Method Calls
+~~~~~~~~~~~~
+
+In Django method calls work implicitly.  With Jinja2 you have to specify that
+you want to call an object.  Thus this Django code::
+
+    {% for page in user.get_created_pages %}
+        ...
+    {% endfor %}
+    
+will look like this in Jinja::
+
+    {% for page in user.get_created_pages() %}
+        ...
+    {% endfor %}
+
+This allows you to pass variables to the function which is also used for macros
+which is not possible in Django.
+
+Conditions
+~~~~~~~~~~
+
+In Django you can use the following constructs to check for equality::
+
+    {% ifequal foo "bar" %}
+        ...
+    {% else %}
+        ...
+    {% endifequal %}
+
+In Jinja2 you can use the normal if statement in combination with operators::
+
+    {% if foo == 'bar' %}
+        ...
+    {% else %}
+        ...
+    {% endif %}
+
+You can also have multiple elif branches in your template::
+
+    {% if something %}
+        ...
+    {% elif otherthing %}
+        ...
+    {% elif foothing %}
+        ...
+    {% else %}
+        ...
+    {% endif %}
+
+Filter Arguments
+~~~~~~~~~~~~~~~~
+
+Jinja2 provides more than one argument for filters.  Also the syntax for
+argument passing is different.  A template that looks like this in Django::
+
+    {{ items|join:", " }}
+
+looks like this in Jinja2::
+
+    {{ items|join(', ') }}
+
+In fact it's a bit more verbose but it allows different types of arguments -
+including variables - and more than one of them.
+
+Tests
+~~~~~
+
+In addition to filters there also are tests you can perform using the is
+operator.  Here are some examples::
+
+    {% if user.user_id is odd %}
+        {{ user.username|e }} is odd
+    {% else %}
+        hmm. {{ user.username|e }} looks pretty normal
+    {% endif %}
+
+Loops
+~~~~~
+
+For loops work very similar to Django, the only incompatibility is that in
+Jinja2 the special variable for the loop context is called `loop` and not
+`forloop` like in Django.
+
+Cycle
+~~~~~
+
+The ``{% cycle %}`` tag does not exist in Jinja because of it's implicit
+nature.  However you can achieve mostly the same by using the `cycle`
+method on a loop object.
+
+The following Django template::
+
+    {% for user in users %}
+        <li class="{% cycle 'odd' 'even' %}">{{ user }}</li>
+    {% endfor %}
+
+Would look like this in Jinja::
+
+    {% for user in users %}
+        <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
+    {% endfor %}
+
+There is no equivalent of ``{% cycle ... as variable %}``.
+
+
+Mako
+----
+
+.. highlight:: html+mako
+
+If you have used Mako so far and want to switch to Jinja2 you can configure
+Jinja2 to look more like Mako:
+
+.. sourcecode:: python
+
+    env = Environment('<%', '%>', '${', '}', '%')
+
+Once the environment is configure like that Jinja2 should be able to interpret
+a small subset of Mako templates.  Jinja2 does not support embedded Python code
+so you would have to move that out of the template.  The syntax for defs (in
+Jinja2 defs are called macros) and template inheritance is different too.  The
+following Mako template::
+
+    <%inherit file="layout.html" />
+    <%def name="title()">Page Title</%def>
+    <ul>
+    % for item in list:
+        <li>${item}</li>
+    % endfor
+    </ul>
+
+Looks like this in Jinja2 with the above configuration::
+
+    <% extends "layout.html" %>
+    <% block title %>Page Title<% endblock %>
+    <% block body %>
+    <ul>
+    % for item in list:
+        <li>${item}</li>
+    % endfor
+    </ul>
+    <% endblock %>


[53/59] [abbrv] git commit: AMBARI-7140. Configs: compare of Scheduler shows individual props, not block of content.(xiwang)

Posted by nc...@apache.org.
AMBARI-7140. Configs: compare of Scheduler shows individual props, not block of content.(xiwang)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/30167824
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/30167824
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/30167824

Branch: refs/heads/branch-alerts-dev
Commit: 30167824be48ed933a5943c3b1e21aa0780f6555
Parents: a599bb8
Author: Xi Wang <xi...@apache.org>
Authored: Wed Sep 3 15:22:32 2014 -0700
Committer: Xi Wang <xi...@apache.org>
Committed: Thu Sep 4 13:00:08 2014 -0700

----------------------------------------------------------------------
 .../controllers/main/service/info/configs.js    | 27 +++++++++++++++-----
 1 file changed, 21 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/30167824/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index 0c58207..663fb36 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -568,16 +568,31 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
     });
 
     json.items[0].configurations.forEach(function (configuration) {
-      for (var prop in configuration.properties) {
-        serviceVersionMap[prop] = {
-          name: prop,
-          value: configuration.properties[prop],
+      if (serviceName == 'YARN' && configuration.type == 'capacity-scheduler') {
+        // put all properties in a single textarea for capacity-scheduler
+        var value = '';
+        for (var prop in configuration.properties) {
+          value += prop + '=' + configuration.properties[prop] + '\n';
+        }
+        serviceVersionMap[configuration.type] = {
+          name: configuration.type,
+          value: value,
           type: configuration.type,
           tag: configuration.tag,
           version: configuration.version
         };
-        if (Em.isNone(configNamesMap[prop])) {
-          allConfigs.push(this.getMockConfig(prop, serviceName, App.config.getOriginalFileName(configuration.type)));
+      } else {
+        for (var prop in configuration.properties) {
+          serviceVersionMap[prop] = {
+            name: prop,
+            value: configuration.properties[prop],
+            type: configuration.type,
+            tag: configuration.tag,
+            version: configuration.version
+          };
+          if (Em.isNone(configNamesMap[prop])) {
+            allConfigs.push(this.getMockConfig(prop, serviceName, App.config.getOriginalFileName(configuration.type)));
+          }
         }
       }
       if (configuration.properties_attributes && configuration.properties_attributes.final) {


[37/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html
deleted file mode 100644
index c4c6303..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/index.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<%!
-  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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html
deleted file mode 100644
index a9c353e..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/layout.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!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/658360a5/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py b/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py
deleted file mode 100644
index 813dd56..0000000
--- a/ambari-common/src/main/python/jinja2/examples/rwbench/rwbench.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# -*- 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 jinja2 import Environment, FileSystemLoader
-from 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/658360a5/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim b/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim
deleted file mode 100644
index 3f9cba4..0000000
--- a/ambari-common/src/main/python/jinja2/ext/Vim/htmljinja.vim
+++ /dev/null
@@ -1,27 +0,0 @@
-" 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/658360a5/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim b/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim
deleted file mode 100644
index 919954b..0000000
--- a/ambari-common/src/main/python/jinja2/ext/Vim/jinja.vim
+++ /dev/null
@@ -1,113 +0,0 @@
-" 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/658360a5/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py b/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py
deleted file mode 100644
index 6d9e76c..0000000
--- a/ambari-common/src/main/python/jinja2/ext/django2jinja/django2jinja.py
+++ /dev/null
@@ -1,768 +0,0 @@
-# -*- 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 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 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/658360a5/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py b/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py
deleted file mode 100644
index 2d4ab9a..0000000
--- a/ambari-common/src/main/python/jinja2/ext/django2jinja/example.py
+++ /dev/null
@@ -1,7 +0,0 @@
-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/658360a5/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html b/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html
deleted file mode 100644
index d0fbe38..0000000
--- a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% 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/658360a5/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html b/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html
deleted file mode 100644
index 3f21a12..0000000
--- a/ambari-common/src/main/python/jinja2/ext/django2jinja/templates/layout.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<title>{% block title %}{% endblock %}</title>
-<div class="body">
-  {% block page-body %}{% endblock %}
-</div>

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

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/ext/djangojinja2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/djangojinja2.py b/ambari-common/src/main/python/jinja2/ext/djangojinja2.py
deleted file mode 100644
index d24d164..0000000
--- a/ambari-common/src/main/python/jinja2/ext/djangojinja2.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    djangojinja2
-    ~~~~~~~~~~~~
-
-    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 jinja2 import Environment, FileSystemLoader, TemplateNotFound
-from 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/658360a5/ambari-common/src/main/python/jinja2/ext/inlinegettext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/inlinegettext.py b/ambari-common/src/main/python/jinja2/ext/inlinegettext.py
deleted file mode 100644
index cf4ed5e..0000000
--- a/ambari-common/src/main/python/jinja2/ext/inlinegettext.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- 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 jinja2.ext import Extension
-from jinja2.lexer import Token, count_newlines
-from 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)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/ext/jinja.el
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/ext/jinja.el b/ambari-common/src/main/python/jinja2/ext/jinja.el
deleted file mode 100644
index 401ba29..0000000
--- a/ambari-common/src/main/python/jinja2/ext/jinja.el
+++ /dev/null
@@ -1,213 +0,0 @@
-;;; jinja.el --- Jinja mode highlighting
-;;
-;; Author: Georg Brandl
-;; Copyright: (c) 2009 by the Jinja Team
-;; Last modified: 2008-05-22 23:04 by gbr
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;; Mostly ripped off django-mode by Lennart Borgman.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or
-;; (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
-;; Floor, Boston, MA 02110-1301, USA.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Code:
-
-(defconst jinja-font-lock-keywords
-  (list
-;   (cons (rx "{% comment %}" (submatch (0+ anything))
-;             "{% endcomment %}") (list 1 font-lock-comment-face))
-   '("{# ?\\(.*?\\) ?#}" . (1 font-lock-comment-face))
-   '("{%-?\\|-?%}\\|{{\\|}}" . font-lock-preprocessor-face)
-   '("{#\\|#}" . font-lock-comment-delimiter-face)
-   ;; first word in a block is a command
-   '("{%-?[ \t\n]*\\([a-zA-Z_]+\\)" . (1 font-lock-keyword-face))
-   ;; variables
-   '("\\({{ ?\\)\\([^|]*?\\)\\(|.*?\\)? ?}}" . (1 font-lock-variable-name-face))
-   ;; keywords and builtins
-   (cons (rx word-start
-             (or "in" "as" "recursive" "not" "and" "or" "if" "else"
-                 "import" "with" "without" "context")
-             word-end)
-         font-lock-keyword-face)
-   (cons (rx word-start
-             (or "true" "false" "none" "loop" "self" "super")
-             word-end)
-         font-lock-builtin-face)
-   ;; tests
-   '("\\(is\\)[ \t]*\\(not\\)[ \t]*\\([a-zA-Z_]+\\)"
-     (1 font-lock-keyword-face) (2 font-lock-keyword-face)
-     (3 font-lock-function-name-face))
-   ;; builtin filters
-   (cons (rx
-          "|" (* space)
-          (submatch
-           (or "abs" "batch" "capitalize" "capture" "center" "count" "default"
-               "dformat" "dictsort" "e" "escape" "filesizeformat" "first"
-               "float" "format" "getattribute" "getitem" "groupby" "indent"
-               "int" "join" "jsonencode" "last" "length" "lower" "markdown"
-               "pprint" "random" "replace" "reverse" "round" "rst" "slice"
-               "sort" "string" "striptags" "sum" "textile" "title" "trim"
-               "truncate" "upper" "urlencode" "urlize" "wordcount" "wordwrap"
-               "xmlattr")))
-         (list 1 font-lock-builtin-face))
-   )
-   "Minimal highlighting expressions for Jinja mode")
-
-(define-derived-mode jinja-mode nil "Jinja"
-  "Simple Jinja mode for use with `mumamo-mode'.
-This mode only provides syntax highlighting."
-  ;;(set (make-local-variable 'comment-start) "{#")
-  ;;(set (make-local-variable 'comment-end)   "#}")
-  (setq font-lock-defaults '(jinja-font-lock-keywords)))
-
-;; mumamo stuff
-
-(when (require 'mumamo nil t)
-
-  (defun mumamo-chunk-jinja3(pos min max)
-    "Find {# ... #}.  Return range and `jinja-mode'.
-See `mumamo-find-possible-chunk' for POS, MIN and MAX."
-    (mumamo-find-possible-chunk pos min max
-                                'mumamo-search-bw-exc-start-jinja3
-                                'mumamo-search-bw-exc-end-jinja3
-                                'mumamo-search-fw-exc-start-jinja3
-                                'mumamo-search-fw-exc-end-jinja3))
-
-  (defun mumamo-chunk-jinja2(pos min max)
-    "Find {{ ... }}.  Return range and `jinja-mode'.
-See `mumamo-find-possible-chunk' for POS, MIN and MAX."
-    (mumamo-find-possible-chunk pos min max
-                                'mumamo-search-bw-exc-start-jinja2
-                                'mumamo-search-bw-exc-end-jinja2
-                                'mumamo-search-fw-exc-start-jinja2
-                                'mumamo-search-fw-exc-end-jinja2))
-
-  (defun mumamo-chunk-jinja (pos min max)
-    "Find {% ... %}.  Return range and `jinja-mode'.
-See `mumamo-find-possible-chunk' for POS, MIN and MAX."
-    (mumamo-find-possible-chunk pos min max
-                                'mumamo-search-bw-exc-start-jinja
-                                'mumamo-search-bw-exc-end-jinja
-                                'mumamo-search-fw-exc-start-jinja
-                                'mumamo-search-fw-exc-end-jinja))
-
-  (defun mumamo-search-bw-exc-start-jinja (pos min)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MIN is where to stop."
-    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{%")))
-      (and exc-start
-           (<= exc-start pos)
-           (cons exc-start 'jinja-mode))))
-
-  (defun mumamo-search-bw-exc-start-jinja2(pos min)
-    "Helper for `mumamo-chunk-jinja2'.
-POS is where to start search and MIN is where to stop."
-    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{{")))
-      (and exc-start
-           (<= exc-start pos)
-           (cons exc-start 'jinja-mode))))
-
-  (defun mumamo-search-bw-exc-start-jinja3(pos min)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MIN is where to stop."
-    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{#")))
-      (and exc-start
-           (<= exc-start pos)
-           (cons exc-start 'jinja-mode))))
-
-  (defun mumamo-search-bw-exc-end-jinja (pos min)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MIN is where to stop."
-    (mumamo-chunk-end-bw-str-inc pos min "%}"))
-
-  (defun mumamo-search-bw-exc-end-jinja2(pos min)
-    "Helper for `mumamo-chunk-jinja2'.
-POS is where to start search and MIN is where to stop."
-    (mumamo-chunk-end-bw-str-inc pos min "}}"))
-
-  (defun mumamo-search-bw-exc-end-jinja3(pos min)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MIN is where to stop."
-    (mumamo-chunk-end-bw-str-inc pos min "#}"))
-
-  (defun mumamo-search-fw-exc-start-jinja (pos max)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-start-fw-str-inc pos max "{%"))
-
-  (defun mumamo-search-fw-exc-start-jinja2(pos max)
-    "Helper for `mumamo-chunk-jinja2'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-start-fw-str-inc pos max "{{"))
-
-  (defun mumamo-search-fw-exc-start-jinja3(pos max)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-start-fw-str-inc pos max "{#"))
-
-  (defun mumamo-search-fw-exc-end-jinja (pos max)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-end-fw-str-inc pos max "%}"))
-
-  (defun mumamo-search-fw-exc-end-jinja2(pos max)
-    "Helper for `mumamo-chunk-jinja2'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-end-fw-str-inc pos max "}}"))
-
-  (defun mumamo-search-fw-exc-end-jinja3(pos max)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-end-fw-str-inc pos max "#}"))
-
-;;;###autoload
-  (define-mumamo-multi-major-mode jinja-html-mumamo
-    "Turn on multiple major modes for Jinja with main mode `html-mode'.
-This also covers inlined style and javascript."
-    ("Jinja HTML Family" html-mode
-     (mumamo-chunk-jinja
-      mumamo-chunk-jinja2
-      mumamo-chunk-jinja3
-      mumamo-chunk-inlined-style
-      mumamo-chunk-inlined-script
-      mumamo-chunk-style=
-      mumamo-chunk-onjs=
-      )))
-
-;;;###autoload
-  (define-mumamo-multi-major-mode jinja-nxhtml-mumamo
-    "Turn on multiple major modes for Jinja with main mode `nxhtml-mode'.
-This also covers inlined style and javascript."
-    ("Jinja nXhtml Family" nxhtml-mode
-     (mumamo-chunk-jinja
-      mumamo-chunk-jinja2
-      mumamo-chunk-jinja3
-      mumamo-chunk-inlined-style
-      mumamo-chunk-inlined-script
-      mumamo-chunk-style=
-      mumamo-chunk-onjs=
-      )))
-  )
-
-(provide 'jinja)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; jinja.el ends here

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2-debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2-debug.py b/ambari-common/src/main/python/jinja2/jinja2-debug.py
deleted file mode 100644
index c9c482f..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2-debug.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-    Jinja2 Debug Interface
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Helper script for internal Jinja2 debugging.  Requires Werkzeug.
-
-    :copyright: Copyright 2010 by Armin Ronacher.
-    :license: BSD.
-"""
-import sys
-import jinja2
-from werkzeug import script
-
-env = jinja2.Environment(extensions=['jinja2.ext.i18n', 'jinja2.ext.do',
-                                     'jinja2.ext.loopcontrols'])
-
-def shell_init_func():
-    def _compile(x):
-        print env.compile(x, raw=True)
-    result = {
-        'e':        env,
-        'c':        _compile,
-        't':        env.from_string,
-        'p':        env.parse
-    }
-    for key in jinja2.__all__:
-        result[key] = getattr(jinja2, key)
-    return result
-
-
-def action_compile():
-    print env.compile(sys.stdin.read(), raw=True)
-
-action_shell = script.make_shell(shell_init_func)
-
-
-if __name__ == '__main__':
-    script.run()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/__init__.py
deleted file mode 100644
index f944e11..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/__init__.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2
-    ~~~~~~
-
-    Jinja2 is a template engine written in pure Python.  It provides a
-    Django inspired non-XML syntax but supports inline expressions and
-    an optional sandboxed environment.
-
-    Nutshell
-    --------
-
-    Here a small example of a Jinja2 template::
-
-        {% extends 'base.html' %}
-        {% block title %}Memberlist{% endblock %}
-        {% block content %}
-          <ul>
-          {% for user in users %}
-            <li><a href="{{ user.url }}">{{ user.username }}</a></li>
-          {% endfor %}
-          </ul>
-        {% endblock %}
-
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-__docformat__ = 'restructuredtext en'
-try:
-    __version__ = __import__('pkg_resources') \
-        .get_distribution('Jinja2').version
-except:
-    __version__ = 'unknown'
-
-# high level interface
-from jinja2.environment import Environment, Template
-
-# loaders
-from jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \
-     DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \
-     ModuleLoader
-
-# bytecode caches
-from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
-     MemcachedBytecodeCache
-
-# undefined types
-from jinja2.runtime import Undefined, DebugUndefined, StrictUndefined
-
-# exceptions
-from jinja2.exceptions import TemplateError, UndefinedError, \
-     TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \
-     TemplateAssertionError
-
-# decorators and public utilities
-from jinja2.filters import environmentfilter, contextfilter, \
-     evalcontextfilter
-from jinja2.utils import Markup, escape, clear_caches, \
-     environmentfunction, evalcontextfunction, contextfunction, \
-     is_undefined
-
-__all__ = [
-    'Environment', 'Template', 'BaseLoader', 'FileSystemLoader',
-    'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader',
-    'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache',
-    'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined',
-    'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound',
-    'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError',
-    'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape',
-    'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined',
-    'evalcontextfilter', 'evalcontextfunction'
-]

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c b/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c
deleted file mode 100644
index e756d8e..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_debugsupport.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * jinja2._debugsupport
- * ~~~~~~~~~~~~~~~~~~~~
- *
- * C implementation of `tb_set_next`.
- *
- * :copyright: (c) 2010 by the Jinja Team.
- * :license: BSD.
- */
-
-#include <Python.h>
-
-
-static PyObject*
-tb_set_next(PyObject *self, PyObject *args)
-{
-	PyTracebackObject *tb, *old;
-	PyObject *next;
-
-	if (!PyArg_ParseTuple(args, "O!O:tb_set_next", &PyTraceBack_Type, &tb, &next))
-		return NULL;
-	if (next == Py_None)
-		next = NULL;
-	else if (!PyTraceBack_Check(next)) {
-		PyErr_SetString(PyExc_TypeError,
-				"tb_set_next arg 2 must be traceback or None");
-		return NULL;
-	}
-	else
-		Py_INCREF(next);
-
-	old = tb->tb_next;
-	tb->tb_next = (PyTracebackObject*)next;
-	Py_XDECREF(old);
-
-	Py_INCREF(Py_None);
-	return Py_None;
-}
-
-static PyMethodDef module_methods[] = {
-	{"tb_set_next", (PyCFunction)tb_set_next, METH_VARARGS,
-	 "Set the tb_next member of a traceback object."},
-	{NULL, NULL, 0, NULL}		/* Sentinel */
-};
-
-
-#if PY_MAJOR_VERSION < 3
-
-#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-init_debugsupport(void)
-{
-	Py_InitModule3("jinja2._debugsupport", module_methods, "");
-}
-
-#else /* Python 3.x module initialization */
-
-static struct PyModuleDef module_definition = {
-        PyModuleDef_HEAD_INIT,
-	"jinja2._debugsupport",
-	NULL,
-	-1,
-	module_methods,
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-PyMODINIT_FUNC
-PyInit__debugsupport(void)
-{
-	return PyModule_Create(&module_definition);
-}
-
-#endif

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py
deleted file mode 100644
index ec7bd57..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/__init__.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    markupsafe
-    ~~~~~~~~~~
-
-    Implements a Markup string.
-
-    :copyright: (c) 2010 by Armin Ronacher.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-from itertools import imap
-
-
-__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
-
-
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
-_entity_re = re.compile(r'&([^;]+);')
-
-
-class Markup(unicode):
-    r"""Marks a string as being safe for inclusion in HTML/XML output without
-    needing to be escaped.  This implements the `__html__` interface a couple
-    of frameworks and web applications use.  :class:`Markup` is a direct
-    subclass of `unicode` and provides all the methods of `unicode` just that
-    it escapes arguments passed and always returns `Markup`.
-
-    The `escape` function returns markup objects so that double escaping can't
-    happen.
-
-    The constructor of the :class:`Markup` class can be used for three
-    different things:  When passed an unicode object it's assumed to be safe,
-    when passed an object with an HTML representation (has an `__html__`
-    method) that representation is used, otherwise the object passed is
-    converted into a unicode string and then assumed to be safe:
-
-    >>> Markup("Hello <em>World</em>!")
-    Markup(u'Hello <em>World</em>!')
-    >>> class Foo(object):
-    ...  def __html__(self):
-    ...   return '<a href="#">foo</a>'
-    ... 
-    >>> Markup(Foo())
-    Markup(u'<a href="#">foo</a>')
-
-    If you want object passed being always treated as unsafe you can use the
-    :meth:`escape` classmethod to create a :class:`Markup` object:
-
-    >>> Markup.escape("Hello <em>World</em>!")
-    Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
-
-    Operations on a markup string are markup aware which means that all
-    arguments are passed through the :func:`escape` function:
-
-    >>> em = Markup("<em>%s</em>")
-    >>> em % "foo & bar"
-    Markup(u'<em>foo &amp; bar</em>')
-    >>> strong = Markup("<strong>%(text)s</strong>")
-    >>> strong % {'text': '<blink>hacker here</blink>'}
-    Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
-    >>> Markup("<em>Hello</em> ") + "<foo>"
-    Markup(u'<em>Hello</em> &lt;foo&gt;')
-    """
-    __slots__ = ()
-
-    def __new__(cls, base=u'', encoding=None, errors='strict'):
-        if hasattr(base, '__html__'):
-            base = base.__html__()
-        if encoding is None:
-            return unicode.__new__(cls, base)
-        return unicode.__new__(cls, base, encoding, errors)
-
-    def __html__(self):
-        return self
-
-    def __add__(self, other):
-        if hasattr(other, '__html__') or isinstance(other, basestring):
-            return self.__class__(unicode(self) + unicode(escape(other)))
-        return NotImplemented
-
-    def __radd__(self, other):
-        if hasattr(other, '__html__') or isinstance(other, basestring):
-            return self.__class__(unicode(escape(other)) + unicode(self))
-        return NotImplemented
-
-    def __mul__(self, num):
-        if isinstance(num, (int, long)):
-            return self.__class__(unicode.__mul__(self, num))
-        return NotImplemented
-    __rmul__ = __mul__
-
-    def __mod__(self, arg):
-        if isinstance(arg, tuple):
-            arg = tuple(imap(_MarkupEscapeHelper, arg))
-        else:
-            arg = _MarkupEscapeHelper(arg)
-        return self.__class__(unicode.__mod__(self, arg))
-
-    def __repr__(self):
-        return '%s(%s)' % (
-            self.__class__.__name__,
-            unicode.__repr__(self)
-        )
-
-    def join(self, seq):
-        return self.__class__(unicode.join(self, imap(escape, seq)))
-    join.__doc__ = unicode.join.__doc__
-
-    def split(self, *args, **kwargs):
-        return map(self.__class__, unicode.split(self, *args, **kwargs))
-    split.__doc__ = unicode.split.__doc__
-
-    def rsplit(self, *args, **kwargs):
-        return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
-    rsplit.__doc__ = unicode.rsplit.__doc__
-
-    def splitlines(self, *args, **kwargs):
-        return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
-    splitlines.__doc__ = unicode.splitlines.__doc__
-
-    def unescape(self):
-        r"""Unescape markup again into an unicode string.  This also resolves
-        known HTML4 and XHTML entities:
-
-        >>> Markup("Main &raquo; <em>About</em>").unescape()
-        u'Main \xbb <em>About</em>'
-        """
-        from jinja2._markupsafe._constants import HTML_ENTITIES
-        def handle_match(m):
-            name = m.group(1)
-            if name in HTML_ENTITIES:
-                return unichr(HTML_ENTITIES[name])
-            try:
-                if name[:2] in ('#x', '#X'):
-                    return unichr(int(name[2:], 16))
-                elif name.startswith('#'):
-                    return unichr(int(name[1:]))
-            except ValueError:
-                pass
-            return u''
-        return _entity_re.sub(handle_match, unicode(self))
-
-    def striptags(self):
-        r"""Unescape markup into an unicode string and strip all tags.  This
-        also resolves known HTML4 and XHTML entities.  Whitespace is
-        normalized to one:
-
-        >>> Markup("Main &raquo;  <em>About</em>").striptags()
-        u'Main \xbb About'
-        """
-        stripped = u' '.join(_striptags_re.sub('', self).split())
-        return Markup(stripped).unescape()
-
-    @classmethod
-    def escape(cls, s):
-        """Escape the string.  Works like :func:`escape` with the difference
-        that for subclasses of :class:`Markup` this function would return the
-        correct subclass.
-        """
-        rv = escape(s)
-        if rv.__class__ is not cls:
-            return cls(rv)
-        return rv
-
-    def make_wrapper(name):
-        orig = getattr(unicode, name)
-        def func(self, *args, **kwargs):
-            args = _escape_argspec(list(args), enumerate(args))
-            _escape_argspec(kwargs, kwargs.iteritems())
-            return self.__class__(orig(self, *args, **kwargs))
-        func.__name__ = orig.__name__
-        func.__doc__ = orig.__doc__
-        return func
-
-    for method in '__getitem__', 'capitalize', \
-                  'title', 'lower', 'upper', 'replace', 'ljust', \
-                  'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
-                  'translate', 'expandtabs', 'swapcase', 'zfill':
-        locals()[method] = make_wrapper(method)
-
-    # new in python 2.5
-    if hasattr(unicode, 'partition'):
-        partition = make_wrapper('partition'),
-        rpartition = make_wrapper('rpartition')
-
-    # new in python 2.6
-    if hasattr(unicode, 'format'):
-        format = make_wrapper('format')
-
-    # not in python 3
-    if hasattr(unicode, '__getslice__'):
-        __getslice__ = make_wrapper('__getslice__')
-
-    del method, make_wrapper
-
-
-def _escape_argspec(obj, iterable):
-    """Helper for various string-wrapped functions."""
-    for key, value in iterable:
-        if hasattr(value, '__html__') or isinstance(value, basestring):
-            obj[key] = escape(value)
-    return obj
-
-
-class _MarkupEscapeHelper(object):
-    """Helper for Markup.__mod__"""
-
-    def __init__(self, obj):
-        self.obj = obj
-
-    __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
-    __str__ = lambda s: str(escape(s.obj))
-    __unicode__ = lambda s: unicode(escape(s.obj))
-    __repr__ = lambda s: str(escape(repr(s.obj)))
-    __int__ = lambda s: int(s.obj)
-    __float__ = lambda s: float(s.obj)
-
-
-# we have to import it down here as the speedups and native
-# modules imports the markup type which is define above.
-try:
-    from jinja2._markupsafe._speedups import escape, escape_silent, soft_unicode
-except ImportError:
-    from jinja2._markupsafe._native import escape, escape_silent, soft_unicode

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py
deleted file mode 100644
index e694faf..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_bundle.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2._markupsafe._bundle
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    This script pulls in markupsafe from a source folder and
-    bundles it with Jinja2.  It does not pull in the speedups
-    module though.
-
-    :copyright: Copyright 2010 by the Jinja team, see AUTHORS.
-    :license: BSD, see LICENSE for details.
-"""
-import sys
-import os
-import re
-
-
-def rewrite_imports(lines):
-    for idx, line in enumerate(lines):
-        new_line = re.sub(r'(import|from)\s+markupsafe\b',
-                          r'\1 jinja2._markupsafe', line)
-        if new_line != line:
-            lines[idx] = new_line
-
-
-def main():
-    if len(sys.argv) != 2:
-        print 'error: only argument is path to markupsafe'
-        sys.exit(1)
-    basedir = os.path.dirname(__file__)
-    markupdir = sys.argv[1]
-    for filename in os.listdir(markupdir):
-        if filename.endswith('.py'):
-            f = open(os.path.join(markupdir, filename))
-            try:
-                lines = list(f)
-            finally:
-                f.close()
-            rewrite_imports(lines)
-            f = open(os.path.join(basedir, filename), 'w')
-            try:
-                for line in lines:
-                    f.write(line)
-            finally:
-                f.close()
-
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py
deleted file mode 100644
index 919bf03..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_constants.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    markupsafe._constants
-    ~~~~~~~~~~~~~~~~~~~~~
-
-    Highlevel implementation of the Markup string.
-
-    :copyright: (c) 2010 by Armin Ronacher.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-HTML_ENTITIES = {
-    'AElig': 198,
-    'Aacute': 193,
-    'Acirc': 194,
-    'Agrave': 192,
-    'Alpha': 913,
-    'Aring': 197,
-    'Atilde': 195,
-    'Auml': 196,
-    'Beta': 914,
-    'Ccedil': 199,
-    'Chi': 935,
-    'Dagger': 8225,
-    'Delta': 916,
-    'ETH': 208,
-    'Eacute': 201,
-    'Ecirc': 202,
-    'Egrave': 200,
-    'Epsilon': 917,
-    'Eta': 919,
-    'Euml': 203,
-    'Gamma': 915,
-    'Iacute': 205,
-    'Icirc': 206,
-    'Igrave': 204,
-    'Iota': 921,
-    'Iuml': 207,
-    'Kappa': 922,
-    'Lambda': 923,
-    'Mu': 924,
-    'Ntilde': 209,
-    'Nu': 925,
-    'OElig': 338,
-    'Oacute': 211,
-    'Ocirc': 212,
-    'Ograve': 210,
-    'Omega': 937,
-    'Omicron': 927,
-    'Oslash': 216,
-    'Otilde': 213,
-    'Ouml': 214,
-    'Phi': 934,
-    'Pi': 928,
-    'Prime': 8243,
-    'Psi': 936,
-    'Rho': 929,
-    'Scaron': 352,
-    'Sigma': 931,
-    'THORN': 222,
-    'Tau': 932,
-    'Theta': 920,
-    'Uacute': 218,
-    'Ucirc': 219,
-    'Ugrave': 217,
-    'Upsilon': 933,
-    'Uuml': 220,
-    'Xi': 926,
-    'Yacute': 221,
-    'Yuml': 376,
-    'Zeta': 918,
-    'aacute': 225,
-    'acirc': 226,
-    'acute': 180,
-    'aelig': 230,
-    'agrave': 224,
-    'alefsym': 8501,
-    'alpha': 945,
-    'amp': 38,
-    'and': 8743,
-    'ang': 8736,
-    'apos': 39,
-    'aring': 229,
-    'asymp': 8776,
-    'atilde': 227,
-    'auml': 228,
-    'bdquo': 8222,
-    'beta': 946,
-    'brvbar': 166,
-    'bull': 8226,
-    'cap': 8745,
-    'ccedil': 231,
-    'cedil': 184,
-    'cent': 162,
-    'chi': 967,
-    'circ': 710,
-    'clubs': 9827,
-    'cong': 8773,
-    'copy': 169,
-    'crarr': 8629,
-    'cup': 8746,
-    'curren': 164,
-    'dArr': 8659,
-    'dagger': 8224,
-    'darr': 8595,
-    'deg': 176,
-    'delta': 948,
-    'diams': 9830,
-    'divide': 247,
-    'eacute': 233,
-    'ecirc': 234,
-    'egrave': 232,
-    'empty': 8709,
-    'emsp': 8195,
-    'ensp': 8194,
-    'epsilon': 949,
-    'equiv': 8801,
-    'eta': 951,
-    'eth': 240,
-    'euml': 235,
-    'euro': 8364,
-    'exist': 8707,
-    'fnof': 402,
-    'forall': 8704,
-    'frac12': 189,
-    'frac14': 188,
-    'frac34': 190,
-    'frasl': 8260,
-    'gamma': 947,
-    'ge': 8805,
-    'gt': 62,
-    'hArr': 8660,
-    'harr': 8596,
-    'hearts': 9829,
-    'hellip': 8230,
-    'iacute': 237,
-    'icirc': 238,
-    'iexcl': 161,
-    'igrave': 236,
-    'image': 8465,
-    'infin': 8734,
-    'int': 8747,
-    'iota': 953,
-    'iquest': 191,
-    'isin': 8712,
-    'iuml': 239,
-    'kappa': 954,
-    'lArr': 8656,
-    'lambda': 955,
-    'lang': 9001,
-    'laquo': 171,
-    'larr': 8592,
-    'lceil': 8968,
-    'ldquo': 8220,
-    'le': 8804,
-    'lfloor': 8970,
-    'lowast': 8727,
-    'loz': 9674,
-    'lrm': 8206,
-    'lsaquo': 8249,
-    'lsquo': 8216,
-    'lt': 60,
-    'macr': 175,
-    'mdash': 8212,
-    'micro': 181,
-    'middot': 183,
-    'minus': 8722,
-    'mu': 956,
-    'nabla': 8711,
-    'nbsp': 160,
-    'ndash': 8211,
-    'ne': 8800,
-    'ni': 8715,
-    'not': 172,
-    'notin': 8713,
-    'nsub': 8836,
-    'ntilde': 241,
-    'nu': 957,
-    'oacute': 243,
-    'ocirc': 244,
-    'oelig': 339,
-    'ograve': 242,
-    'oline': 8254,
-    'omega': 969,
-    'omicron': 959,
-    'oplus': 8853,
-    'or': 8744,
-    'ordf': 170,
-    'ordm': 186,
-    'oslash': 248,
-    'otilde': 245,
-    'otimes': 8855,
-    'ouml': 246,
-    'para': 182,
-    'part': 8706,
-    'permil': 8240,
-    'perp': 8869,
-    'phi': 966,
-    'pi': 960,
-    'piv': 982,
-    'plusmn': 177,
-    'pound': 163,
-    'prime': 8242,
-    'prod': 8719,
-    'prop': 8733,
-    'psi': 968,
-    'quot': 34,
-    'rArr': 8658,
-    'radic': 8730,
-    'rang': 9002,
-    'raquo': 187,
-    'rarr': 8594,
-    'rceil': 8969,
-    'rdquo': 8221,
-    'real': 8476,
-    'reg': 174,
-    'rfloor': 8971,
-    'rho': 961,
-    'rlm': 8207,
-    'rsaquo': 8250,
-    'rsquo': 8217,
-    'sbquo': 8218,
-    'scaron': 353,
-    'sdot': 8901,
-    'sect': 167,
-    'shy': 173,
-    'sigma': 963,
-    'sigmaf': 962,
-    'sim': 8764,
-    'spades': 9824,
-    'sub': 8834,
-    'sube': 8838,
-    'sum': 8721,
-    'sup': 8835,
-    'sup1': 185,
-    'sup2': 178,
-    'sup3': 179,
-    'supe': 8839,
-    'szlig': 223,
-    'tau': 964,
-    'there4': 8756,
-    'theta': 952,
-    'thetasym': 977,
-    'thinsp': 8201,
-    'thorn': 254,
-    'tilde': 732,
-    'times': 215,
-    'trade': 8482,
-    'uArr': 8657,
-    'uacute': 250,
-    'uarr': 8593,
-    'ucirc': 251,
-    'ugrave': 249,
-    'uml': 168,
-    'upsih': 978,
-    'upsilon': 965,
-    'uuml': 252,
-    'weierp': 8472,
-    'xi': 958,
-    'yacute': 253,
-    'yen': 165,
-    'yuml': 255,
-    'zeta': 950,
-    'zwj': 8205,
-    'zwnj': 8204
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py
deleted file mode 100644
index 7b95828..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/_native.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    markupsafe._native
-    ~~~~~~~~~~~~~~~~~~
-
-    Native Python implementation the C module is not compiled.
-
-    :copyright: (c) 2010 by Armin Ronacher.
-    :license: BSD, see LICENSE for more details.
-"""
-from jinja2._markupsafe import Markup
-
-
-def escape(s):
-    """Convert the characters &, <, >, ' and " in string s to HTML-safe
-    sequences.  Use this if you need to display text that might contain
-    such characters in HTML.  Marks return value as markup string.
-    """
-    if hasattr(s, '__html__'):
-        return s.__html__()
-    return Markup(unicode(s)
-        .replace('&', '&amp;')
-        .replace('>', '&gt;')
-        .replace('<', '&lt;')
-        .replace("'", '&#39;')
-        .replace('"', '&#34;')
-    )
-
-
-def escape_silent(s):
-    """Like :func:`escape` but converts `None` into an empty
-    markup string.
-    """
-    if s is None:
-        return Markup()
-    return escape(s)
-
-
-def soft_unicode(s):
-    """Make a string unicode if it isn't already.  That way a markup
-    string is not converted back to unicode.
-    """
-    if not isinstance(s, unicode):
-        s = unicode(s)
-    return s

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py b/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py
deleted file mode 100644
index c1ce394..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/_markupsafe/tests.py
+++ /dev/null
@@ -1,80 +0,0 @@
-import gc
-import unittest
-from jinja2._markupsafe import Markup, escape, escape_silent
-
-
-class MarkupTestCase(unittest.TestCase):
-
-    def test_markup_operations(self):
-        # adding two strings should escape the unsafe one
-        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
-        safe = Markup('<em>username</em>')
-        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
-
-        # string interpolations are safe to use too
-        assert Markup('<em>%s</em>') % '<bad user>' == \
-               '<em>&lt;bad user&gt;</em>'
-        assert Markup('<em>%(username)s</em>') % {
-            'username': '<bad user>'
-        } == '<em>&lt;bad user&gt;</em>'
-
-        # an escaped object is markup too
-        assert type(Markup('foo') + 'bar') is Markup
-
-        # and it implements __html__ by returning itself
-        x = Markup("foo")
-        assert x.__html__() is x
-
-        # it also knows how to treat __html__ objects
-        class Foo(object):
-            def __html__(self):
-                return '<em>awesome</em>'
-            def __unicode__(self):
-                return 'awesome'
-        assert Markup(Foo()) == '<em>awesome</em>'
-        assert Markup('<strong>%s</strong>') % Foo() == \
-               '<strong><em>awesome</em></strong>'
-
-        # escaping and unescaping
-        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
-        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
-        assert Markup("&lt;test&gt;").unescape() == "<test>"
-
-    def test_all_set(self):
-        import jinja2._markupsafe as markup
-        for item in markup.__all__:
-            getattr(markup, item)
-
-    def test_escape_silent(self):
-        assert escape_silent(None) == Markup()
-        assert escape(None) == Markup(None)
-        assert escape_silent('<foo>') == Markup(u'&lt;foo&gt;')
-
-
-class MarkupLeakTestCase(unittest.TestCase):
-
-    def test_markup_leaks(self):
-        counts = set()
-        for count in xrange(20):
-            for item in xrange(1000):
-                escape("foo")
-                escape("<foo>")
-                escape(u"foo")
-                escape(u"<foo>")
-            counts.add(len(gc.get_objects()))
-        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(MarkupTestCase))
-
-    # this test only tests the c extension
-    if not hasattr(escape, 'func_code'):
-        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
-
-    return suite
-
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='suite')


[34/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/environment.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/environment.py b/ambari-common/src/main/python/jinja2/jinja2/environment.py
deleted file mode 100644
index ac74a5c..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/environment.py
+++ /dev/null
@@ -1,1118 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.environment
-    ~~~~~~~~~~~~~~~~~~
-
-    Provides a class that holds runtime and parsing time options.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-from jinja2 import nodes
-from jinja2.defaults import *
-from jinja2.lexer import get_lexer, TokenStream
-from jinja2.parser import Parser
-from jinja2.optimizer import optimize
-from jinja2.compiler import generate
-from jinja2.runtime import Undefined, new_context
-from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
-     TemplatesNotFound
-from jinja2.utils import import_string, LRUCache, Markup, missing, \
-     concat, consume, internalcode, _encode_filename
-
-
-# for direct template usage we have up to ten living environments
-_spontaneous_environments = LRUCache(10)
-
-# the function to create jinja traceback objects.  This is dynamically
-# imported on the first exception in the exception handler.
-_make_traceback = None
-
-
-def get_spontaneous_environment(*args):
-    """Return a new spontaneous environment.  A spontaneous environment is an
-    unnamed and unaccessible (in theory) environment that is used for
-    templates generated from a string and not from the file system.
-    """
-    try:
-        env = _spontaneous_environments.get(args)
-    except TypeError:
-        return Environment(*args)
-    if env is not None:
-        return env
-    _spontaneous_environments[args] = env = Environment(*args)
-    env.shared = True
-    return env
-
-
-def create_cache(size):
-    """Return the cache class for the given size."""
-    if size == 0:
-        return None
-    if size < 0:
-        return {}
-    return LRUCache(size)
-
-
-def copy_cache(cache):
-    """Create an empty copy of the given cache."""
-    if cache is None:
-        return None
-    elif type(cache) is dict:
-        return {}
-    return LRUCache(cache.capacity)
-
-
-def load_extensions(environment, extensions):
-    """Load the extensions from the list and bind it to the environment.
-    Returns a dict of instanciated environments.
-    """
-    result = {}
-    for extension in extensions:
-        if isinstance(extension, basestring):
-            extension = import_string(extension)
-        result[extension.identifier] = extension(environment)
-    return result
-
-
-def _environment_sanity_check(environment):
-    """Perform a sanity check on the environment."""
-    assert issubclass(environment.undefined, Undefined), 'undefined must ' \
-           'be a subclass of undefined because filters depend on it.'
-    assert environment.block_start_string != \
-           environment.variable_start_string != \
-           environment.comment_start_string, 'block, variable and comment ' \
-           'start strings must be different'
-    assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
-           'newline_sequence set to unknown line ending string.'
-    return environment
-
-
-class Environment(object):
-    r"""The core component of Jinja is the `Environment`.  It contains
-    important shared variables like configuration, filters, tests,
-    globals and others.  Instances of this class may be modified if
-    they are not shared and if no template was loaded so far.
-    Modifications on environments after the first template was loaded
-    will lead to surprising effects and undefined behavior.
-
-    Here the possible initialization parameters:
-
-        `block_start_string`
-            The string marking the begin of a block.  Defaults to ``'{%'``.
-
-        `block_end_string`
-            The string marking the end of a block.  Defaults to ``'%}'``.
-
-        `variable_start_string`
-            The string marking the begin of a print statement.
-            Defaults to ``'{{'``.
-
-        `variable_end_string`
-            The string marking the end of a print statement.  Defaults to
-            ``'}}'``.
-
-        `comment_start_string`
-            The string marking the begin of a comment.  Defaults to ``'{#'``.
-
-        `comment_end_string`
-            The string marking the end of a comment.  Defaults to ``'#}'``.
-
-        `line_statement_prefix`
-            If given and a string, this will be used as prefix for line based
-            statements.  See also :ref:`line-statements`.
-
-        `line_comment_prefix`
-            If given and a string, this will be used as prefix for line based
-            based comments.  See also :ref:`line-statements`.
-
-            .. versionadded:: 2.2
-
-        `trim_blocks`
-            If this is set to ``True`` the first newline after a block is
-            removed (block, not variable tag!).  Defaults to `False`.
-
-        `newline_sequence`
-            The sequence that starts a newline.  Must be one of ``'\r'``,
-            ``'\n'`` or ``'\r\n'``.  The default is ``'\n'`` which is a
-            useful default for Linux and OS X systems as well as web
-            applications.
-
-        `extensions`
-            List of Jinja extensions to use.  This can either be import paths
-            as strings or extension classes.  For more information have a
-            look at :ref:`the extensions documentation <jinja-extensions>`.
-
-        `optimized`
-            should the optimizer be enabled?  Default is `True`.
-
-        `undefined`
-            :class:`Undefined` or a subclass of it that is used to represent
-            undefined values in the template.
-
-        `finalize`
-            A callable that can be used to process the result of a variable
-            expression before it is output.  For example one can convert
-            `None` implicitly into an empty string here.
-
-        `autoescape`
-            If set to true the XML/HTML autoescaping feature is enabled by
-            default.  For more details about auto escaping see
-            :class:`~jinja2.utils.Markup`.  As of Jinja 2.4 this can also
-            be a callable that is passed the template name and has to
-            return `True` or `False` depending on autoescape should be
-            enabled by default.
-
-            .. versionchanged:: 2.4
-               `autoescape` can now be a function
-
-        `loader`
-            The template loader for this environment.
-
-        `cache_size`
-            The size of the cache.  Per default this is ``50`` which means
-            that if more than 50 templates are loaded the loader will clean
-            out the least recently used template.  If the cache size is set to
-            ``0`` templates are recompiled all the time, if the cache size is
-            ``-1`` the cache will not be cleaned.
-
-        `auto_reload`
-            Some loaders load templates from locations where the template
-            sources may change (ie: file system or database).  If
-            `auto_reload` is set to `True` (default) every time a template is
-            requested the loader checks if the source changed and if yes, it
-            will reload the template.  For higher performance it's possible to
-            disable that.
-
-        `bytecode_cache`
-            If set to a bytecode cache object, this object will provide a
-            cache for the internal Jinja bytecode so that templates don't
-            have to be parsed if they were not changed.
-
-            See :ref:`bytecode-cache` for more information.
-    """
-
-    #: if this environment is sandboxed.  Modifying this variable won't make
-    #: the environment sandboxed though.  For a real sandboxed environment
-    #: have a look at jinja2.sandbox
-    sandboxed = False
-
-    #: True if the environment is just an overlay
-    overlayed = False
-
-    #: the environment this environment is linked to if it is an overlay
-    linked_to = None
-
-    #: shared environments have this set to `True`.  A shared environment
-    #: must not be modified
-    shared = False
-
-    #: these are currently EXPERIMENTAL undocumented features.
-    exception_handler = None
-    exception_formatter = None
-
-    def __init__(self,
-                 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,
-                 line_statement_prefix=LINE_STATEMENT_PREFIX,
-                 line_comment_prefix=LINE_COMMENT_PREFIX,
-                 trim_blocks=TRIM_BLOCKS,
-                 newline_sequence=NEWLINE_SEQUENCE,
-                 extensions=(),
-                 optimized=True,
-                 undefined=Undefined,
-                 finalize=None,
-                 autoescape=False,
-                 loader=None,
-                 cache_size=50,
-                 auto_reload=True,
-                 bytecode_cache=None):
-        # !!Important notice!!
-        #   The constructor accepts quite a few arguments that should be
-        #   passed by keyword rather than position.  However it's important to
-        #   not change the order of arguments because it's used at least
-        #   internally in those cases:
-        #       -   spontaneus environments (i18n extension and Template)
-        #       -   unittests
-        #   If parameter changes are required only add parameters at the end
-        #   and don't change the arguments (or the defaults!) of the arguments
-        #   existing already.
-
-        # lexer / parser information
-        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.line_statement_prefix = line_statement_prefix
-        self.line_comment_prefix = line_comment_prefix
-        self.trim_blocks = trim_blocks
-        self.newline_sequence = newline_sequence
-
-        # runtime information
-        self.undefined = undefined
-        self.optimized = optimized
-        self.finalize = finalize
-        self.autoescape = autoescape
-
-        # defaults
-        self.filters = DEFAULT_FILTERS.copy()
-        self.tests = DEFAULT_TESTS.copy()
-        self.globals = DEFAULT_NAMESPACE.copy()
-
-        # set the loader provided
-        self.loader = loader
-        self.bytecode_cache = None
-        self.cache = create_cache(cache_size)
-        self.bytecode_cache = bytecode_cache
-        self.auto_reload = auto_reload
-
-        # load extensions
-        self.extensions = load_extensions(self, extensions)
-
-        _environment_sanity_check(self)
-
-    def add_extension(self, extension):
-        """Adds an extension after the environment was created.
-
-        .. versionadded:: 2.5
-        """
-        self.extensions.update(load_extensions(self, [extension]))
-
-    def extend(self, **attributes):
-        """Add the items to the instance of the environment if they do not exist
-        yet.  This is used by :ref:`extensions <writing-extensions>` to register
-        callbacks and configuration values without breaking inheritance.
-        """
-        for key, value in attributes.iteritems():
-            if not hasattr(self, key):
-                setattr(self, key, value)
-
-    def overlay(self, block_start_string=missing, block_end_string=missing,
-                variable_start_string=missing, variable_end_string=missing,
-                comment_start_string=missing, comment_end_string=missing,
-                line_statement_prefix=missing, line_comment_prefix=missing,
-                trim_blocks=missing, extensions=missing, optimized=missing,
-                undefined=missing, finalize=missing, autoescape=missing,
-                loader=missing, cache_size=missing, auto_reload=missing,
-                bytecode_cache=missing):
-        """Create a new overlay environment that shares all the data with the
-        current environment except of cache and the overridden attributes.
-        Extensions cannot be removed for an overlayed environment.  An overlayed
-        environment automatically gets all the extensions of the environment it
-        is linked to plus optional extra extensions.
-
-        Creating overlays should happen after the initial environment was set
-        up completely.  Not all attributes are truly linked, some are just
-        copied over so modifications on the original environment may not shine
-        through.
-        """
-        args = dict(locals())
-        del args['self'], args['cache_size'], args['extensions']
-
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.overlayed = True
-        rv.linked_to = self
-
-        for key, value in args.iteritems():
-            if value is not missing:
-                setattr(rv, key, value)
-
-        if cache_size is not missing:
-            rv.cache = create_cache(cache_size)
-        else:
-            rv.cache = copy_cache(self.cache)
-
-        rv.extensions = {}
-        for key, value in self.extensions.iteritems():
-            rv.extensions[key] = value.bind(rv)
-        if extensions is not missing:
-            rv.extensions.update(load_extensions(rv, extensions))
-
-        return _environment_sanity_check(rv)
-
-    lexer = property(get_lexer, doc="The lexer for this environment.")
-
-    def iter_extensions(self):
-        """Iterates over the extensions by priority."""
-        return iter(sorted(self.extensions.values(),
-                           key=lambda x: x.priority))
-
-    def getitem(self, obj, argument):
-        """Get an item or attribute of an object but prefer the item."""
-        try:
-            return obj[argument]
-        except (TypeError, LookupError):
-            if isinstance(argument, basestring):
-                try:
-                    attr = str(argument)
-                except:
-                    pass
-                else:
-                    try:
-                        return getattr(obj, attr)
-                    except AttributeError:
-                        pass
-            return self.undefined(obj=obj, name=argument)
-
-    def getattr(self, obj, attribute):
-        """Get an item or attribute of an object but prefer the attribute.
-        Unlike :meth:`getitem` the attribute *must* be a bytestring.
-        """
-        try:
-            return getattr(obj, attribute)
-        except AttributeError:
-            pass
-        try:
-            return obj[attribute]
-        except (TypeError, LookupError, AttributeError):
-            return self.undefined(obj=obj, name=attribute)
-
-    @internalcode
-    def parse(self, source, name=None, filename=None):
-        """Parse the sourcecode and return the abstract syntax tree.  This
-        tree of nodes is used by the compiler to convert the template into
-        executable source- or bytecode.  This is useful for debugging or to
-        extract information from templates.
-
-        If you are :ref:`developing Jinja2 extensions <writing-extensions>`
-        this gives you a good overview of the node tree generated.
-        """
-        try:
-            return self._parse(source, name, filename)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        self.handle_exception(exc_info, source_hint=source)
-
-    def _parse(self, source, name, filename):
-        """Internal parsing function used by `parse` and `compile`."""
-        return Parser(self, source, name, _encode_filename(filename)).parse()
-
-    def lex(self, source, name=None, filename=None):
-        """Lex the given sourcecode and return a generator that yields
-        tokens as tuples in the form ``(lineno, token_type, value)``.
-        This can be useful for :ref:`extension development <writing-extensions>`
-        and debugging templates.
-
-        This does not perform preprocessing.  If you want the preprocessing
-        of the extensions to be applied you have to filter source through
-        the :meth:`preprocess` method.
-        """
-        source = unicode(source)
-        try:
-            return self.lexer.tokeniter(source, name, filename)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        self.handle_exception(exc_info, source_hint=source)
-
-    def preprocess(self, source, name=None, filename=None):
-        """Preprocesses the source with all extensions.  This is automatically
-        called for all parsing and compiling methods but *not* for :meth:`lex`
-        because there you usually only want the actual source tokenized.
-        """
-        return reduce(lambda s, e: e.preprocess(s, name, filename),
-                      self.iter_extensions(), unicode(source))
-
-    def _tokenize(self, source, name, filename=None, state=None):
-        """Called by the parser to do the preprocessing and filtering
-        for all the extensions.  Returns a :class:`~jinja2.lexer.TokenStream`.
-        """
-        source = self.preprocess(source, name, filename)
-        stream = self.lexer.tokenize(source, name, filename, state)
-        for ext in self.iter_extensions():
-            stream = ext.filter_stream(stream)
-            if not isinstance(stream, TokenStream):
-                stream = TokenStream(stream, name, filename)
-        return stream
-
-    def _generate(self, source, name, filename, defer_init=False):
-        """Internal hook that can be overriden to hook a different generate
-        method in.
-
-        .. versionadded:: 2.5
-        """
-        return generate(source, self, name, filename, defer_init=defer_init)
-
-    def _compile(self, source, filename):
-        """Internal hook that can be overriden to hook a different compile
-        method in.
-
-        .. versionadded:: 2.5
-        """
-        return compile(source, filename, 'exec')
-
-    @internalcode
-    def compile(self, source, name=None, filename=None, raw=False,
-                defer_init=False):
-        """Compile a node or template source code.  The `name` parameter is
-        the load name of the template after it was joined using
-        :meth:`join_path` if necessary, not the filename on the file system.
-        the `filename` parameter is the estimated filename of the template on
-        the file system.  If the template came from a database or memory this
-        can be omitted.
-
-        The return value of this method is a python code object.  If the `raw`
-        parameter is `True` the return value will be a string with python
-        code equivalent to the bytecode returned otherwise.  This method is
-        mainly used internally.
-
-        `defer_init` is use internally to aid the module code generator.  This
-        causes the generated code to be able to import without the global
-        environment variable to be set.
-
-        .. versionadded:: 2.4
-           `defer_init` parameter added.
-        """
-        source_hint = None
-        try:
-            if isinstance(source, basestring):
-                source_hint = source
-                source = self._parse(source, name, filename)
-            if self.optimized:
-                source = optimize(source, self)
-            source = self._generate(source, name, filename,
-                                    defer_init=defer_init)
-            if raw:
-                return source
-            if filename is None:
-                filename = '<template>'
-            else:
-                filename = _encode_filename(filename)
-            return self._compile(source, filename)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        self.handle_exception(exc_info, source_hint=source)
-
-    def compile_expression(self, source, undefined_to_none=True):
-        """A handy helper method that returns a callable that accepts keyword
-        arguments that appear as variables in the expression.  If called it
-        returns the result of the expression.
-
-        This is useful if applications want to use the same rules as Jinja
-        in template "configuration files" or similar situations.
-
-        Example usage:
-
-        >>> env = Environment()
-        >>> expr = env.compile_expression('foo == 42')
-        >>> expr(foo=23)
-        False
-        >>> expr(foo=42)
-        True
-
-        Per default the return value is converted to `None` if the
-        expression returns an undefined value.  This can be changed
-        by setting `undefined_to_none` to `False`.
-
-        >>> env.compile_expression('var')() is None
-        True
-        >>> env.compile_expression('var', undefined_to_none=False)()
-        Undefined
-
-        .. versionadded:: 2.1
-        """
-        parser = Parser(self, source, state='variable')
-        exc_info = None
-        try:
-            expr = parser.parse_expression()
-            if not parser.stream.eos:
-                raise TemplateSyntaxError('chunk after expression',
-                                          parser.stream.current.lineno,
-                                          None, None)
-            expr.set_environment(self)
-        except TemplateSyntaxError:
-            exc_info = sys.exc_info()
-        if exc_info is not None:
-            self.handle_exception(exc_info, source_hint=source)
-        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
-        template = self.from_string(nodes.Template(body, lineno=1))
-        return TemplateExpression(template, undefined_to_none)
-
-    def compile_templates(self, target, extensions=None, filter_func=None,
-                          zip='deflated', log_function=None,
-                          ignore_errors=True, py_compile=False):
-        """Compiles all the templates the loader can find, compiles them
-        and stores them in `target`.  If `zip` is `None`, instead of in a
-        zipfile, the templates will be will be stored in a directory.
-        By default a deflate zip algorithm is used, to switch to
-        the stored algorithm, `zip` can be set to ``'stored'``.
-
-        `extensions` and `filter_func` are passed to :meth:`list_templates`.
-        Each template returned will be compiled to the target folder or
-        zipfile.
-
-        By default template compilation errors are ignored.  In case a
-        log function is provided, errors are logged.  If you want template
-        syntax errors to abort the compilation you can set `ignore_errors`
-        to `False` and you will get an exception on syntax errors.
-
-        If `py_compile` is set to `True` .pyc files will be written to the
-        target instead of standard .py files.
-
-        .. versionadded:: 2.4
-        """
-        from jinja2.loaders import ModuleLoader
-
-        if log_function is None:
-            log_function = lambda x: None
-
-        if py_compile:
-            import imp, struct, marshal
-            py_header = imp.get_magic() + \
-                u'\xff\xff\xff\xff'.encode('iso-8859-15')
-
-        def write_file(filename, data, mode):
-            if zip:
-                info = ZipInfo(filename)
-                info.external_attr = 0755 << 16L
-                zip_file.writestr(info, data)
-            else:
-                f = open(os.path.join(target, filename), mode)
-                try:
-                    f.write(data)
-                finally:
-                    f.close()
-
-        if zip is not None:
-            from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
-            zip_file = ZipFile(target, 'w', dict(deflated=ZIP_DEFLATED,
-                                                 stored=ZIP_STORED)[zip])
-            log_function('Compiling into Zip archive "%s"' % target)
-        else:
-            if not os.path.isdir(target):
-                os.makedirs(target)
-            log_function('Compiling into folder "%s"' % target)
-
-        try:
-            for name in self.list_templates(extensions, filter_func):
-                source, filename, _ = self.loader.get_source(self, name)
-                try:
-                    code = self.compile(source, name, filename, True, True)
-                except TemplateSyntaxError, e:
-                    if not ignore_errors:
-                        raise
-                    log_function('Could not compile "%s": %s' % (name, e))
-                    continue
-
-                filename = ModuleLoader.get_module_filename(name)
-
-                if py_compile:
-                    c = self._compile(code, _encode_filename(filename))
-                    write_file(filename + 'c', py_header +
-                               marshal.dumps(c), 'wb')
-                    log_function('Byte-compiled "%s" as %s' %
-                                 (name, filename + 'c'))
-                else:
-                    write_file(filename, code, 'w')
-                    log_function('Compiled "%s" as %s' % (name, filename))
-        finally:
-            if zip:
-                zip_file.close()
-
-        log_function('Finished compiling templates')
-
-    def list_templates(self, extensions=None, filter_func=None):
-        """Returns a list of templates for this environment.  This requires
-        that the loader supports the loader's
-        :meth:`~BaseLoader.list_templates` method.
-
-        If there are other files in the template folder besides the
-        actual templates, the returned list can be filtered.  There are two
-        ways: either `extensions` is set to a list of file extensions for
-        templates, or a `filter_func` can be provided which is a callable that
-        is passed a template name and should return `True` if it should end up
-        in the result list.
-
-        If the loader does not support that, a :exc:`TypeError` is raised.
-        """
-        x = self.loader.list_templates()
-        if extensions is not None:
-            if filter_func is not None:
-                raise TypeError('either extensions or filter_func '
-                                'can be passed, but not both')
-            filter_func = lambda x: '.' in x and \
-                                    x.rsplit('.', 1)[1] in extensions
-        if filter_func is not None:
-            x = filter(filter_func, x)
-        return x
-
-    def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
-        """Exception handling helper.  This is used internally to either raise
-        rewritten exceptions or return a rendered traceback for the template.
-        """
-        global _make_traceback
-        if exc_info is None:
-            exc_info = sys.exc_info()
-
-        # the debugging module is imported when it's used for the first time.
-        # we're doing a lot of stuff there and for applications that do not
-        # get any exceptions in template rendering there is no need to load
-        # all of that.
-        if _make_traceback is None:
-            from jinja2.debug import make_traceback as _make_traceback
-        traceback = _make_traceback(exc_info, source_hint)
-        if rendered and self.exception_formatter is not None:
-            return self.exception_formatter(traceback)
-        if self.exception_handler is not None:
-            self.exception_handler(traceback)
-        exc_type, exc_value, tb = traceback.standard_exc_info
-        raise exc_type, exc_value, tb
-
-    def join_path(self, template, parent):
-        """Join a template with the parent.  By default all the lookups are
-        relative to the loader root so this method returns the `template`
-        parameter unchanged, but if the paths should be relative to the
-        parent template, this function can be used to calculate the real
-        template name.
-
-        Subclasses may override this method and implement template path
-        joining here.
-        """
-        return template
-
-    @internalcode
-    def _load_template(self, name, globals):
-        if self.loader is None:
-            raise TypeError('no loader for this environment specified')
-        if self.cache is not None:
-            template = self.cache.get(name)
-            if template is not None and (not self.auto_reload or \
-                                         template.is_up_to_date):
-                return template
-        template = self.loader.load(self, name, globals)
-        if self.cache is not None:
-            self.cache[name] = template
-        return template
-
-    @internalcode
-    def get_template(self, name, parent=None, globals=None):
-        """Load a template from the loader.  If a loader is configured this
-        method ask the loader for the template and returns a :class:`Template`.
-        If the `parent` parameter is not `None`, :meth:`join_path` is called
-        to get the real template name before loading.
-
-        The `globals` parameter can be used to provide template wide globals.
-        These variables are available in the context at render time.
-
-        If the template does not exist a :exc:`TemplateNotFound` exception is
-        raised.
-
-        .. versionchanged:: 2.4
-           If `name` is a :class:`Template` object it is returned from the
-           function unchanged.
-        """
-        if isinstance(name, Template):
-            return name
-        if parent is not None:
-            name = self.join_path(name, parent)
-        return self._load_template(name, self.make_globals(globals))
-
-    @internalcode
-    def select_template(self, names, parent=None, globals=None):
-        """Works like :meth:`get_template` but tries a number of templates
-        before it fails.  If it cannot find any of the templates, it will
-        raise a :exc:`TemplatesNotFound` exception.
-
-        .. versionadded:: 2.3
-
-        .. versionchanged:: 2.4
-           If `names` contains a :class:`Template` object it is returned
-           from the function unchanged.
-        """
-        if not names:
-            raise TemplatesNotFound(message=u'Tried to select from an empty list '
-                                            u'of templates.')
-        globals = self.make_globals(globals)
-        for name in names:
-            if isinstance(name, Template):
-                return name
-            if parent is not None:
-                name = self.join_path(name, parent)
-            try:
-                return self._load_template(name, globals)
-            except TemplateNotFound:
-                pass
-        raise TemplatesNotFound(names)
-
-    @internalcode
-    def get_or_select_template(self, template_name_or_list,
-                               parent=None, globals=None):
-        """Does a typecheck and dispatches to :meth:`select_template`
-        if an iterable of template names is given, otherwise to
-        :meth:`get_template`.
-
-        .. versionadded:: 2.3
-        """
-        if isinstance(template_name_or_list, basestring):
-            return self.get_template(template_name_or_list, parent, globals)
-        elif isinstance(template_name_or_list, Template):
-            return template_name_or_list
-        return self.select_template(template_name_or_list, parent, globals)
-
-    def from_string(self, source, globals=None, template_class=None):
-        """Load a template from a string.  This parses the source given and
-        returns a :class:`Template` object.
-        """
-        globals = self.make_globals(globals)
-        cls = template_class or self.template_class
-        return cls.from_code(self, self.compile(source), globals, None)
-
-    def make_globals(self, d):
-        """Return a dict for the globals."""
-        if not d:
-            return self.globals
-        return dict(self.globals, **d)
-
-
-class Template(object):
-    """The central template object.  This class represents a compiled template
-    and is used to evaluate it.
-
-    Normally the template object is generated from an :class:`Environment` but
-    it also has a constructor that makes it possible to create a template
-    instance directly using the constructor.  It takes the same arguments as
-    the environment constructor but it's not possible to specify a loader.
-
-    Every template object has a few methods and members that are guaranteed
-    to exist.  However it's important that a template object should be
-    considered immutable.  Modifications on the object are not supported.
-
-    Template objects created from the constructor rather than an environment
-    do have an `environment` attribute that points to a temporary environment
-    that is probably shared with other templates created with the constructor
-    and compatible settings.
-
-    >>> template = Template('Hello {{ name }}!')
-    >>> template.render(name='John Doe')
-    u'Hello John Doe!'
-
-    >>> stream = template.stream(name='John Doe')
-    >>> stream.next()
-    u'Hello John Doe!'
-    >>> stream.next()
-    Traceback (most recent call last):
-        ...
-    StopIteration
-    """
-
-    def __new__(cls, source,
-                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,
-                line_statement_prefix=LINE_STATEMENT_PREFIX,
-                line_comment_prefix=LINE_COMMENT_PREFIX,
-                trim_blocks=TRIM_BLOCKS,
-                newline_sequence=NEWLINE_SEQUENCE,
-                extensions=(),
-                optimized=True,
-                undefined=Undefined,
-                finalize=None,
-                autoescape=False):
-        env = get_spontaneous_environment(
-            block_start_string, block_end_string, variable_start_string,
-            variable_end_string, comment_start_string, comment_end_string,
-            line_statement_prefix, line_comment_prefix, trim_blocks,
-            newline_sequence, frozenset(extensions), optimized, undefined,
-            finalize, autoescape, None, 0, False, None)
-        return env.from_string(source, template_class=cls)
-
-    @classmethod
-    def from_code(cls, environment, code, globals, uptodate=None):
-        """Creates a template object from compiled code and the globals.  This
-        is used by the loaders and environment to create a template object.
-        """
-        namespace = {
-            'environment':  environment,
-            '__file__':     code.co_filename
-        }
-        exec code in namespace
-        rv = cls._from_namespace(environment, namespace, globals)
-        rv._uptodate = uptodate
-        return rv
-
-    @classmethod
-    def from_module_dict(cls, environment, module_dict, globals):
-        """Creates a template object from a module.  This is used by the
-        module loader to create a template object.
-
-        .. versionadded:: 2.4
-        """
-        return cls._from_namespace(environment, module_dict, globals)
-
-    @classmethod
-    def _from_namespace(cls, environment, namespace, globals):
-        t = object.__new__(cls)
-        t.environment = environment
-        t.globals = globals
-        t.name = namespace['name']
-        t.filename = namespace['__file__']
-        t.blocks = namespace['blocks']
-
-        # render function and module
-        t.root_render_func = namespace['root']
-        t._module = None
-
-        # debug and loader helpers
-        t._debug_info = namespace['debug_info']
-        t._uptodate = None
-
-        # store the reference
-        namespace['environment'] = environment
-        namespace['__jinja_template__'] = t
-
-        return t
-
-    def render(self, *args, **kwargs):
-        """This method accepts the same arguments as the `dict` constructor:
-        A dict, a dict subclass or some keyword arguments.  If no arguments
-        are given the context will be empty.  These two calls do the same::
-
-            template.render(knights='that say nih')
-            template.render({'knights': 'that say nih'})
-
-        This will return the rendered template as unicode string.
-        """
-        vars = dict(*args, **kwargs)
-        try:
-            return concat(self.root_render_func(self.new_context(vars)))
-        except:
-            exc_info = sys.exc_info()
-        return self.environment.handle_exception(exc_info, True)
-
-    def stream(self, *args, **kwargs):
-        """Works exactly like :meth:`generate` but returns a
-        :class:`TemplateStream`.
-        """
-        return TemplateStream(self.generate(*args, **kwargs))
-
-    def generate(self, *args, **kwargs):
-        """For very large templates it can be useful to not render the whole
-        template at once but evaluate each statement after another and yield
-        piece for piece.  This method basically does exactly that and returns
-        a generator that yields one item after another as unicode strings.
-
-        It accepts the same arguments as :meth:`render`.
-        """
-        vars = dict(*args, **kwargs)
-        try:
-            for event in self.root_render_func(self.new_context(vars)):
-                yield event
-        except:
-            exc_info = sys.exc_info()
-        else:
-            return
-        yield self.environment.handle_exception(exc_info, True)
-
-    def new_context(self, vars=None, shared=False, locals=None):
-        """Create a new :class:`Context` for this template.  The vars
-        provided will be passed to the template.  Per default the globals
-        are added to the context.  If shared is set to `True` the data
-        is passed as it to the context without adding the globals.
-
-        `locals` can be a dict of local variables for internal usage.
-        """
-        return new_context(self.environment, self.name, self.blocks,
-                           vars, shared, self.globals, locals)
-
-    def make_module(self, vars=None, shared=False, locals=None):
-        """This method works like the :attr:`module` attribute when called
-        without arguments but it will evaluate the template on every call
-        rather than caching it.  It's also possible to provide
-        a dict which is then used as context.  The arguments are the same
-        as for the :meth:`new_context` method.
-        """
-        return TemplateModule(self, self.new_context(vars, shared, locals))
-
-    @property
-    def module(self):
-        """The template as module.  This is used for imports in the
-        template runtime but is also useful if one wants to access
-        exported template variables from the Python layer:
-
-        >>> t = Template('{% macro foo() %}42{% endmacro %}23')
-        >>> unicode(t.module)
-        u'23'
-        >>> t.module.foo()
-        u'42'
-        """
-        if self._module is not None:
-            return self._module
-        self._module = rv = self.make_module()
-        return rv
-
-    def get_corresponding_lineno(self, lineno):
-        """Return the source line number of a line number in the
-        generated bytecode as they are not in sync.
-        """
-        for template_line, code_line in reversed(self.debug_info):
-            if code_line <= lineno:
-                return template_line
-        return 1
-
-    @property
-    def is_up_to_date(self):
-        """If this variable is `False` there is a newer version available."""
-        if self._uptodate is None:
-            return True
-        return self._uptodate()
-
-    @property
-    def debug_info(self):
-        """The debug info mapping."""
-        return [tuple(map(int, x.split('='))) for x in
-                self._debug_info.split('&')]
-
-    def __repr__(self):
-        if self.name is None:
-            name = 'memory:%x' % id(self)
-        else:
-            name = repr(self.name)
-        return '<%s %s>' % (self.__class__.__name__, name)
-
-
-class TemplateModule(object):
-    """Represents an imported template.  All the exported names of the
-    template are available as attributes on this object.  Additionally
-    converting it into an unicode- or bytestrings renders the contents.
-    """
-
-    def __init__(self, template, context):
-        self._body_stream = list(template.root_render_func(context))
-        self.__dict__.update(context.get_exported())
-        self.__name__ = template.name
-
-    def __html__(self):
-        return Markup(concat(self._body_stream))
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        return concat(self._body_stream)
-
-    def __repr__(self):
-        if self.__name__ is None:
-            name = 'memory:%x' % id(self)
-        else:
-            name = repr(self.__name__)
-        return '<%s %s>' % (self.__class__.__name__, name)
-
-
-class TemplateExpression(object):
-    """The :meth:`jinja2.Environment.compile_expression` method returns an
-    instance of this object.  It encapsulates the expression-like access
-    to the template with an expression it wraps.
-    """
-
-    def __init__(self, template, undefined_to_none):
-        self._template = template
-        self._undefined_to_none = undefined_to_none
-
-    def __call__(self, *args, **kwargs):
-        context = self._template.new_context(dict(*args, **kwargs))
-        consume(self._template.root_render_func(context))
-        rv = context.vars['result']
-        if self._undefined_to_none and isinstance(rv, Undefined):
-            rv = None
-        return rv
-
-
-class TemplateStream(object):
-    """A template stream works pretty much like an ordinary python generator
-    but it can buffer multiple items to reduce the number of total iterations.
-    Per default the output is unbuffered which means that for every unbuffered
-    instruction in the template one unicode string is yielded.
-
-    If buffering is enabled with a buffer size of 5, five items are combined
-    into a new unicode string.  This is mainly useful if you are streaming
-    big templates to a client via WSGI which flushes after each iteration.
-    """
-
-    def __init__(self, gen):
-        self._gen = gen
-        self.disable_buffering()
-
-    def dump(self, fp, encoding=None, errors='strict'):
-        """Dump the complete stream into a file or file-like object.
-        Per default unicode strings are written, if you want to encode
-        before writing specifiy an `encoding`.
-
-        Example usage::
-
-            Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
-        """
-        close = False
-        if isinstance(fp, basestring):
-            fp = file(fp, 'w')
-            close = True
-        try:
-            if encoding is not None:
-                iterable = (x.encode(encoding, errors) for x in self)
-            else:
-                iterable = self
-            if hasattr(fp, 'writelines'):
-                fp.writelines(iterable)
-            else:
-                for item in iterable:
-                    fp.write(item)
-        finally:
-            if close:
-                fp.close()
-
-    def disable_buffering(self):
-        """Disable the output buffering."""
-        self._next = self._gen.next
-        self.buffered = False
-
-    def enable_buffering(self, size=5):
-        """Enable buffering.  Buffer `size` items before yielding them."""
-        if size <= 1:
-            raise ValueError('buffer size too small')
-
-        def generator(next):
-            buf = []
-            c_size = 0
-            push = buf.append
-
-            while 1:
-                try:
-                    while c_size < size:
-                        c = next()
-                        push(c)
-                        if c:
-                            c_size += 1
-                except StopIteration:
-                    if not c_size:
-                        return
-                yield concat(buf)
-                del buf[:]
-                c_size = 0
-
-        self.buffered = True
-        self._next = generator(self._gen.next).next
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        return self._next()
-
-
-# hook in default template class.  if anyone reads this comment: ignore that
-# it's possible to use custom templates ;-)
-Environment.template_class = Template

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/exceptions.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/exceptions.py b/ambari-common/src/main/python/jinja2/jinja2/exceptions.py
deleted file mode 100644
index 771f6a8..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/exceptions.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.exceptions
-    ~~~~~~~~~~~~~~~~~
-
-    Jinja exceptions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-class TemplateError(Exception):
-    """Baseclass for all template errors."""
-
-    def __init__(self, message=None):
-        if message is not None:
-            message = unicode(message).encode('utf-8')
-        Exception.__init__(self, message)
-
-    @property
-    def message(self):
-        if self.args:
-            message = self.args[0]
-            if message is not None:
-                return message.decode('utf-8', 'replace')
-
-
-class TemplateNotFound(IOError, LookupError, TemplateError):
-    """Raised if a template does not exist."""
-
-    # looks weird, but removes the warning descriptor that just
-    # bogusly warns us about message being deprecated
-    message = None
-
-    def __init__(self, name, message=None):
-        IOError.__init__(self)
-        if message is None:
-            message = name
-        self.message = message
-        self.name = name
-        self.templates = [name]
-
-    def __str__(self):
-        return self.message.encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        return self.message
-
-
-class TemplatesNotFound(TemplateNotFound):
-    """Like :class:`TemplateNotFound` but raised if multiple templates
-    are selected.  This is a subclass of :class:`TemplateNotFound`
-    exception, so just catching the base exception will catch both.
-
-    .. versionadded:: 2.2
-    """
-
-    def __init__(self, names=(), message=None):
-        if message is None:
-            message = u'non of the templates given were found: ' + \
-                      u', '.join(map(unicode, names))
-        TemplateNotFound.__init__(self, names and names[-1] or None, message)
-        self.templates = list(names)
-
-
-class TemplateSyntaxError(TemplateError):
-    """Raised to tell the user that there is a problem with the template."""
-
-    def __init__(self, message, lineno, name=None, filename=None):
-        TemplateError.__init__(self, message)
-        self.lineno = lineno
-        self.name = name
-        self.filename = filename
-        self.source = None
-
-        # this is set to True if the debug.translate_syntax_error
-        # function translated the syntax error into a new traceback
-        self.translated = False
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    # unicode goes after __str__ because we configured 2to3 to rename
-    # __unicode__ to __str__.  because the 2to3 tree is not designed to
-    # remove nodes from it, we leave the above __str__ around and let
-    # it override at runtime.
-    def __unicode__(self):
-        # for translated errors we only return the message
-        if self.translated:
-            return self.message
-
-        # otherwise attach some stuff
-        location = 'line %d' % self.lineno
-        name = self.filename or self.name
-        if name:
-            location = 'File "%s", %s' % (name, location)
-        lines = [self.message, '  ' + location]
-
-        # if the source is set, add the line to the output
-        if self.source is not None:
-            try:
-                line = self.source.splitlines()[self.lineno - 1]
-            except IndexError:
-                line = None
-            if line:
-                lines.append('    ' + line.strip())
-
-        return u'\n'.join(lines)
-
-
-class TemplateAssertionError(TemplateSyntaxError):
-    """Like a template syntax error, but covers cases where something in the
-    template caused an error at compile time that wasn't necessarily caused
-    by a syntax error.  However it's a direct subclass of
-    :exc:`TemplateSyntaxError` and has the same attributes.
-    """
-
-
-class TemplateRuntimeError(TemplateError):
-    """A generic runtime error in the template engine.  Under some situations
-    Jinja may raise this exception.
-    """
-
-
-class UndefinedError(TemplateRuntimeError):
-    """Raised if a template tries to operate on :class:`Undefined`."""
-
-
-class SecurityError(TemplateRuntimeError):
-    """Raised if a template tries to do something insecure if the
-    sandbox is enabled.
-    """
-
-
-class FilterArgumentError(TemplateRuntimeError):
-    """This error is raised if a filter was called with inappropriate
-    arguments
-    """

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/ext.py b/ambari-common/src/main/python/jinja2/jinja2/ext.py
deleted file mode 100644
index ceb3895..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/ext.py
+++ /dev/null
@@ -1,610 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.ext
-    ~~~~~~~~~~
-
-    Jinja extensions allow to add custom tags similar to the way django custom
-    tags work.  By default two example extensions exist: an i18n and a cache
-    extension.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from collections import deque
-from jinja2 import nodes
-from jinja2.defaults import *
-from jinja2.environment import Environment
-from jinja2.runtime import Undefined, concat
-from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
-from jinja2.utils import contextfunction, import_string, Markup, next
-
-
-# the only real useful gettext functions for a Jinja template.  Note
-# that ugettext must be assigned to gettext as Jinja doesn't support
-# non unicode strings.
-GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext')
-
-
-class ExtensionRegistry(type):
-    """Gives the extension an unique identifier."""
-
-    def __new__(cls, name, bases, d):
-        rv = type.__new__(cls, name, bases, d)
-        rv.identifier = rv.__module__ + '.' + rv.__name__
-        return rv
-
-
-class Extension(object):
-    """Extensions can be used to add extra functionality to the Jinja template
-    system at the parser level.  Custom extensions are bound to an environment
-    but may not store environment specific data on `self`.  The reason for
-    this is that an extension can be bound to another environment (for
-    overlays) by creating a copy and reassigning the `environment` attribute.
-
-    As extensions are created by the environment they cannot accept any
-    arguments for configuration.  One may want to work around that by using
-    a factory function, but that is not possible as extensions are identified
-    by their import name.  The correct way to configure the extension is
-    storing the configuration values on the environment.  Because this way the
-    environment ends up acting as central configuration storage the
-    attributes may clash which is why extensions have to ensure that the names
-    they choose for configuration are not too generic.  ``prefix`` for example
-    is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
-    name as includes the name of the extension (fragment cache).
-    """
-    __metaclass__ = ExtensionRegistry
-
-    #: if this extension parses this is the list of tags it's listening to.
-    tags = set()
-
-    #: the priority of that extension.  This is especially useful for
-    #: extensions that preprocess values.  A lower value means higher
-    #: priority.
-    #:
-    #: .. versionadded:: 2.4
-    priority = 100
-
-    def __init__(self, environment):
-        self.environment = environment
-
-    def bind(self, environment):
-        """Create a copy of this extension bound to another environment."""
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.environment = environment
-        return rv
-
-    def preprocess(self, source, name, filename=None):
-        """This method is called before the actual lexing and can be used to
-        preprocess the source.  The `filename` is optional.  The return value
-        must be the preprocessed source.
-        """
-        return source
-
-    def filter_stream(self, stream):
-        """It's passed a :class:`~jinja2.lexer.TokenStream` that can be used
-        to filter tokens returned.  This method has to return an iterable of
-        :class:`~jinja2.lexer.Token`\s, but it doesn't have to return a
-        :class:`~jinja2.lexer.TokenStream`.
-
-        In the `ext` folder of the Jinja2 source distribution there is a file
-        called `inlinegettext.py` which implements a filter that utilizes this
-        method.
-        """
-        return stream
-
-    def parse(self, parser):
-        """If any of the :attr:`tags` matched this method is called with the
-        parser as first argument.  The token the parser stream is pointing at
-        is the name token that matched.  This method has to return one or a
-        list of multiple nodes.
-        """
-        raise NotImplementedError()
-
-    def attr(self, name, lineno=None):
-        """Return an attribute node for the current extension.  This is useful
-        to pass constants on extensions to generated template code::
-
-            self.attr('_my_attribute', lineno=lineno)
-        """
-        return nodes.ExtensionAttribute(self.identifier, name, lineno=lineno)
-
-    def call_method(self, name, args=None, kwargs=None, dyn_args=None,
-                    dyn_kwargs=None, lineno=None):
-        """Call a method of the extension.  This is a shortcut for
-        :meth:`attr` + :class:`jinja2.nodes.Call`.
-        """
-        if args is None:
-            args = []
-        if kwargs is None:
-            kwargs = []
-        return nodes.Call(self.attr(name, lineno=lineno), args, kwargs,
-                          dyn_args, dyn_kwargs, lineno=lineno)
-
-
-@contextfunction
-def _gettext_alias(__context, *args, **kwargs):
-    return __context.call(__context.resolve('gettext'), *args, **kwargs)
-
-
-def _make_new_gettext(func):
-    @contextfunction
-    def gettext(__context, __string, **variables):
-        rv = __context.call(func, __string)
-        if __context.eval_ctx.autoescape:
-            rv = Markup(rv)
-        return rv % variables
-    return gettext
-
-
-def _make_new_ngettext(func):
-    @contextfunction
-    def ngettext(__context, __singular, __plural, __num, **variables):
-        variables.setdefault('num', __num)
-        rv = __context.call(func, __singular, __plural, __num)
-        if __context.eval_ctx.autoescape:
-            rv = Markup(rv)
-        return rv % variables
-    return ngettext
-
-
-class InternationalizationExtension(Extension):
-    """This extension adds gettext support to Jinja2."""
-    tags = set(['trans'])
-
-    # TODO: the i18n extension is currently reevaluating values in a few
-    # situations.  Take this example:
-    #   {% trans count=something() %}{{ count }} foo{% pluralize
-    #     %}{{ count }} fooss{% endtrans %}
-    # something is called twice here.  One time for the gettext value and
-    # the other time for the n-parameter of the ngettext function.
-
-    def __init__(self, environment):
-        Extension.__init__(self, environment)
-        environment.globals['_'] = _gettext_alias
-        environment.extend(
-            install_gettext_translations=self._install,
-            install_null_translations=self._install_null,
-            install_gettext_callables=self._install_callables,
-            uninstall_gettext_translations=self._uninstall,
-            extract_translations=self._extract,
-            newstyle_gettext=False
-        )
-
-    def _install(self, translations, newstyle=None):
-        gettext = getattr(translations, 'ugettext', None)
-        if gettext is None:
-            gettext = translations.gettext
-        ngettext = getattr(translations, 'ungettext', None)
-        if ngettext is None:
-            ngettext = translations.ngettext
-        self._install_callables(gettext, ngettext, newstyle)
-
-    def _install_null(self, newstyle=None):
-        self._install_callables(
-            lambda x: x,
-            lambda s, p, n: (n != 1 and (p,) or (s,))[0],
-            newstyle
-        )
-
-    def _install_callables(self, gettext, ngettext, newstyle=None):
-        if newstyle is not None:
-            self.environment.newstyle_gettext = newstyle
-        if self.environment.newstyle_gettext:
-            gettext = _make_new_gettext(gettext)
-            ngettext = _make_new_ngettext(ngettext)
-        self.environment.globals.update(
-            gettext=gettext,
-            ngettext=ngettext
-        )
-
-    def _uninstall(self, translations):
-        for key in 'gettext', 'ngettext':
-            self.environment.globals.pop(key, None)
-
-    def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
-        if isinstance(source, basestring):
-            source = self.environment.parse(source)
-        return extract_from_ast(source, gettext_functions)
-
-    def parse(self, parser):
-        """Parse a translatable tag."""
-        lineno = next(parser.stream).lineno
-        num_called_num = False
-
-        # find all the variables referenced.  Additionally a variable can be
-        # defined in the body of the trans block too, but this is checked at
-        # a later state.
-        plural_expr = None
-        variables = {}
-        while parser.stream.current.type != 'block_end':
-            if variables:
-                parser.stream.expect('comma')
-
-            # skip colon for python compatibility
-            if parser.stream.skip_if('colon'):
-                break
-
-            name = parser.stream.expect('name')
-            if name.value in variables:
-                parser.fail('translatable variable %r defined twice.' %
-                            name.value, name.lineno,
-                            exc=TemplateAssertionError)
-
-            # expressions
-            if parser.stream.current.type == 'assign':
-                next(parser.stream)
-                variables[name.value] = var = parser.parse_expression()
-            else:
-                variables[name.value] = var = nodes.Name(name.value, 'load')
-
-            if plural_expr is None:
-                plural_expr = var
-                num_called_num = name.value == 'num'
-
-        parser.stream.expect('block_end')
-
-        plural = plural_names = None
-        have_plural = False
-        referenced = set()
-
-        # now parse until endtrans or pluralize
-        singular_names, singular = self._parse_block(parser, True)
-        if singular_names:
-            referenced.update(singular_names)
-            if plural_expr is None:
-                plural_expr = nodes.Name(singular_names[0], 'load')
-                num_called_num = singular_names[0] == 'num'
-
-        # if we have a pluralize block, we parse that too
-        if parser.stream.current.test('name:pluralize'):
-            have_plural = True
-            next(parser.stream)
-            if parser.stream.current.type != 'block_end':
-                name = parser.stream.expect('name')
-                if name.value not in variables:
-                    parser.fail('unknown variable %r for pluralization' %
-                                name.value, name.lineno,
-                                exc=TemplateAssertionError)
-                plural_expr = variables[name.value]
-                num_called_num = name.value == 'num'
-            parser.stream.expect('block_end')
-            plural_names, plural = self._parse_block(parser, False)
-            next(parser.stream)
-            referenced.update(plural_names)
-        else:
-            next(parser.stream)
-
-        # register free names as simple name expressions
-        for var in referenced:
-            if var not in variables:
-                variables[var] = nodes.Name(var, 'load')
-
-        if not have_plural:
-            plural_expr = None
-        elif plural_expr is None:
-            parser.fail('pluralize without variables', lineno)
-
-        node = self._make_node(singular, plural, variables, plural_expr,
-                               bool(referenced),
-                               num_called_num and have_plural)
-        node.set_lineno(lineno)
-        return node
-
-    def _parse_block(self, parser, allow_pluralize):
-        """Parse until the next block tag with a given name."""
-        referenced = []
-        buf = []
-        while 1:
-            if parser.stream.current.type == 'data':
-                buf.append(parser.stream.current.value.replace('%', '%%'))
-                next(parser.stream)
-            elif parser.stream.current.type == 'variable_begin':
-                next(parser.stream)
-                name = parser.stream.expect('name').value
-                referenced.append(name)
-                buf.append('%%(%s)s' % name)
-                parser.stream.expect('variable_end')
-            elif parser.stream.current.type == 'block_begin':
-                next(parser.stream)
-                if parser.stream.current.test('name:endtrans'):
-                    break
-                elif parser.stream.current.test('name:pluralize'):
-                    if allow_pluralize:
-                        break
-                    parser.fail('a translatable section can have only one '
-                                'pluralize section')
-                parser.fail('control structures in translatable sections are '
-                            'not allowed')
-            elif parser.stream.eos:
-                parser.fail('unclosed translation block')
-            else:
-                assert False, 'internal parser error'
-
-        return referenced, concat(buf)
-
-    def _make_node(self, singular, plural, variables, plural_expr,
-                   vars_referenced, num_called_num):
-        """Generates a useful node from the data provided."""
-        # no variables referenced?  no need to escape for old style
-        # gettext invocations only if there are vars.
-        if not vars_referenced and not self.environment.newstyle_gettext:
-            singular = singular.replace('%%', '%')
-            if plural:
-                plural = plural.replace('%%', '%')
-
-        # singular only:
-        if plural_expr is None:
-            gettext = nodes.Name('gettext', 'load')
-            node = nodes.Call(gettext, [nodes.Const(singular)],
-                              [], None, None)
-
-        # singular and plural
-        else:
-            ngettext = nodes.Name('ngettext', 'load')
-            node = nodes.Call(ngettext, [
-                nodes.Const(singular),
-                nodes.Const(plural),
-                plural_expr
-            ], [], None, None)
-
-        # in case newstyle gettext is used, the method is powerful
-        # enough to handle the variable expansion and autoescape
-        # handling itself
-        if self.environment.newstyle_gettext:
-            for key, value in variables.iteritems():
-                # the function adds that later anyways in case num was
-                # called num, so just skip it.
-                if num_called_num and key == 'num':
-                    continue
-                node.kwargs.append(nodes.Keyword(key, value))
-
-        # otherwise do that here
-        else:
-            # mark the return value as safe if we are in an
-            # environment with autoescaping turned on
-            node = nodes.MarkSafeIfAutoescape(node)
-            if variables:
-                node = nodes.Mod(node, nodes.Dict([
-                    nodes.Pair(nodes.Const(key), value)
-                    for key, value in variables.items()
-                ]))
-        return nodes.Output([node])
-
-
-class ExprStmtExtension(Extension):
-    """Adds a `do` tag to Jinja2 that works like the print statement just
-    that it doesn't print the return value.
-    """
-    tags = set(['do'])
-
-    def parse(self, parser):
-        node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
-        node.node = parser.parse_tuple()
-        return node
-
-
-class LoopControlExtension(Extension):
-    """Adds break and continue to the template engine."""
-    tags = set(['break', 'continue'])
-
-    def parse(self, parser):
-        token = next(parser.stream)
-        if token.value == 'break':
-            return nodes.Break(lineno=token.lineno)
-        return nodes.Continue(lineno=token.lineno)
-
-
-class WithExtension(Extension):
-    """Adds support for a django-like with block."""
-    tags = set(['with'])
-
-    def parse(self, parser):
-        node = nodes.Scope(lineno=next(parser.stream).lineno)
-        assignments = []
-        while parser.stream.current.type != 'block_end':
-            lineno = parser.stream.current.lineno
-            if assignments:
-                parser.stream.expect('comma')
-            target = parser.parse_assign_target()
-            parser.stream.expect('assign')
-            expr = parser.parse_expression()
-            assignments.append(nodes.Assign(target, expr, lineno=lineno))
-        node.body = assignments + \
-            list(parser.parse_statements(('name:endwith',),
-                                         drop_needle=True))
-        return node
-
-
-class AutoEscapeExtension(Extension):
-    """Changes auto escape rules for a scope."""
-    tags = set(['autoescape'])
-
-    def parse(self, parser):
-        node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
-        node.options = [
-            nodes.Keyword('autoescape', parser.parse_expression())
-        ]
-        node.body = parser.parse_statements(('name:endautoescape',),
-                                            drop_needle=True)
-        return nodes.Scope([node])
-
-
-def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
-                     babel_style=True):
-    """Extract localizable strings from the given template node.  Per
-    default this function returns matches in babel style that means non string
-    parameters as well as keyword arguments are returned as `None`.  This
-    allows Babel to figure out what you really meant if you are using
-    gettext functions that allow keyword arguments for placeholder expansion.
-    If you don't want that behavior set the `babel_style` parameter to `False`
-    which causes only strings to be returned and parameters are always stored
-    in tuples.  As a consequence invalid gettext calls (calls without a single
-    string parameter or string parameters after non-string parameters) are
-    skipped.
-
-    This example explains the behavior:
-
-    >>> from jinja2 import Environment
-    >>> env = Environment()
-    >>> node = env.parse('{{ (_("foo"), _(), ngettext("foo", "bar", 42)) }}')
-    >>> list(extract_from_ast(node))
-    [(1, '_', 'foo'), (1, '_', ()), (1, 'ngettext', ('foo', 'bar', None))]
-    >>> list(extract_from_ast(node, babel_style=False))
-    [(1, '_', ('foo',)), (1, 'ngettext', ('foo', 'bar'))]
-
-    For every string found this function yields a ``(lineno, function,
-    message)`` tuple, where:
-
-    * ``lineno`` is the number of the line on which the string was found,
-    * ``function`` is the name of the ``gettext`` function used (if the
-      string was extracted from embedded Python code), and
-    *  ``message`` is the string itself (a ``unicode`` object, or a tuple
-       of ``unicode`` objects for functions with multiple string arguments).
-
-    This extraction function operates on the AST and is because of that unable
-    to extract any comments.  For comment support you have to use the babel
-    extraction interface or extract comments yourself.
-    """
-    for node in node.find_all(nodes.Call):
-        if not isinstance(node.node, nodes.Name) or \
-           node.node.name not in gettext_functions:
-            continue
-
-        strings = []
-        for arg in node.args:
-            if isinstance(arg, nodes.Const) and \
-               isinstance(arg.value, basestring):
-                strings.append(arg.value)
-            else:
-                strings.append(None)
-
-        for arg in node.kwargs:
-            strings.append(None)
-        if node.dyn_args is not None:
-            strings.append(None)
-        if node.dyn_kwargs is not None:
-            strings.append(None)
-
-        if not babel_style:
-            strings = tuple(x for x in strings if x is not None)
-            if not strings:
-                continue
-        else:
-            if len(strings) == 1:
-                strings = strings[0]
-            else:
-                strings = tuple(strings)
-        yield node.lineno, node.node.name, strings
-
-
-class _CommentFinder(object):
-    """Helper class to find comments in a token stream.  Can only
-    find comments for gettext calls forwards.  Once the comment
-    from line 4 is found, a comment for line 1 will not return a
-    usable value.
-    """
-
-    def __init__(self, tokens, comment_tags):
-        self.tokens = tokens
-        self.comment_tags = comment_tags
-        self.offset = 0
-        self.last_lineno = 0
-
-    def find_backwards(self, offset):
-        try:
-            for _, token_type, token_value in \
-                    reversed(self.tokens[self.offset:offset]):
-                if token_type in ('comment', 'linecomment'):
-                    try:
-                        prefix, comment = token_value.split(None, 1)
-                    except ValueError:
-                        continue
-                    if prefix in self.comment_tags:
-                        return [comment.rstrip()]
-            return []
-        finally:
-            self.offset = offset
-
-    def find_comments(self, lineno):
-        if not self.comment_tags or self.last_lineno > lineno:
-            return []
-        for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset:]):
-            if token_lineno > lineno:
-                return self.find_backwards(self.offset + idx)
-        return self.find_backwards(len(self.tokens))
-
-
-def babel_extract(fileobj, keywords, comment_tags, options):
-    """Babel extraction method for Jinja templates.
-
-    .. versionchanged:: 2.3
-       Basic support for translation comments was added.  If `comment_tags`
-       is now set to a list of keywords for extraction, the extractor will
-       try to find the best preceeding comment that begins with one of the
-       keywords.  For best results, make sure to not have more than one
-       gettext call in one line of code and the matching comment in the
-       same line or the line before.
-
-    .. versionchanged:: 2.5.1
-       The `newstyle_gettext` flag can be set to `True` to enable newstyle
-       gettext calls.
-
-    :param fileobj: the file-like object the messages should be extracted from
-    :param keywords: a list of keywords (i.e. function names) that should be
-                     recognized as translation functions
-    :param comment_tags: a list of translator tags to search for and include
-                         in the results.
-    :param options: a dictionary of additional options (optional)
-    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
-             (comments will be empty currently)
-    """
-    extensions = set()
-    for extension in options.get('extensions', '').split(','):
-        extension = extension.strip()
-        if not extension:
-            continue
-        extensions.add(import_string(extension))
-    if InternationalizationExtension not in extensions:
-        extensions.add(InternationalizationExtension)
-
-    def getbool(options, key, default=False):
-        options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true')
-
-    environment = Environment(
-        options.get('block_start_string', BLOCK_START_STRING),
-        options.get('block_end_string', BLOCK_END_STRING),
-        options.get('variable_start_string', VARIABLE_START_STRING),
-        options.get('variable_end_string', VARIABLE_END_STRING),
-        options.get('comment_start_string', COMMENT_START_STRING),
-        options.get('comment_end_string', COMMENT_END_STRING),
-        options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
-        options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
-        getbool(options, 'trim_blocks', TRIM_BLOCKS),
-        NEWLINE_SEQUENCE, frozenset(extensions),
-        cache_size=0,
-        auto_reload=False
-    )
-
-    if getbool(options, 'newstyle_gettext'):
-        environment.newstyle_gettext = True
-
-    source = fileobj.read().decode(options.get('encoding', 'utf-8'))
-    try:
-        node = environment.parse(source)
-        tokens = list(environment.lex(environment.preprocess(source)))
-    except TemplateSyntaxError, e:
-        # skip templates with syntax errors
-        return
-
-    finder = _CommentFinder(tokens, comment_tags)
-    for lineno, func, message in extract_from_ast(node, keywords):
-        yield lineno, func, message, finder.find_comments(lineno)
-
-
-#: nicer import names
-i18n = InternationalizationExtension
-do = ExprStmtExtension
-loopcontrols = LoopControlExtension
-with_ = WithExtension
-autoescape = AutoEscapeExtension


[11/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el b/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el
deleted file mode 100644
index da4800a..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ext/jinja.el
+++ /dev/null
@@ -1,213 +0,0 @@
-;;; jinja.el --- Jinja mode highlighting
-;;
-;; Author: Georg Brandl
-;; Copyright: (c) 2009 by the Jinja Team
-;; Last modified: 2008-05-22 23:04 by gbr
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;; Mostly ripped off django-mode by Lennart Borgman.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or
-;; (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
-;; Floor, Boston, MA 02110-1301, USA.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Code:
-
-(defconst jinja-font-lock-keywords
-  (list
-;   (cons (rx "{% comment %}" (submatch (0+ anything))
-;             "{% endcomment %}") (list 1 font-lock-comment-face))
-   '("{# ?\\(.*?\\) ?#}" . (1 font-lock-comment-face))
-   '("{%-?\\|-?%}\\|{{\\|}}" . font-lock-preprocessor-face)
-   '("{#\\|#}" . font-lock-comment-delimiter-face)
-   ;; first word in a block is a command
-   '("{%-?[ \t\n]*\\([a-zA-Z_]+\\)" . (1 font-lock-keyword-face))
-   ;; variables
-   '("\\({{ ?\\)\\([^|]*?\\)\\(|.*?\\)? ?}}" . (1 font-lock-variable-name-face))
-   ;; keywords and builtins
-   (cons (rx word-start
-             (or "in" "as" "recursive" "not" "and" "or" "if" "else"
-                 "import" "with" "without" "context")
-             word-end)
-         font-lock-keyword-face)
-   (cons (rx word-start
-             (or "true" "false" "none" "loop" "self" "super")
-             word-end)
-         font-lock-builtin-face)
-   ;; tests
-   '("\\(is\\)[ \t]*\\(not\\)[ \t]*\\([a-zA-Z_]+\\)"
-     (1 font-lock-keyword-face) (2 font-lock-keyword-face)
-     (3 font-lock-function-name-face))
-   ;; builtin filters
-   (cons (rx
-          "|" (* space)
-          (submatch
-           (or "abs" "batch" "capitalize" "capture" "center" "count" "default"
-               "dformat" "dictsort" "e" "escape" "filesizeformat" "first"
-               "float" "format" "getattribute" "getitem" "groupby" "indent"
-               "int" "join" "jsonencode" "last" "length" "lower" "markdown"
-               "pprint" "random" "replace" "reverse" "round" "rst" "slice"
-               "sort" "string" "striptags" "sum" "textile" "title" "trim"
-               "truncate" "upper" "urlencode" "urlize" "wordcount" "wordwrap"
-               "xmlattr")))
-         (list 1 font-lock-builtin-face))
-   )
-   "Minimal highlighting expressions for Jinja mode")
-
-(define-derived-mode jinja-mode nil "Jinja"
-  "Simple Jinja mode for use with `mumamo-mode'.
-This mode only provides syntax highlighting."
-  ;;(set (make-local-variable 'comment-start) "{#")
-  ;;(set (make-local-variable 'comment-end)   "#}")
-  (setq font-lock-defaults '(jinja-font-lock-keywords)))
-
-;; mumamo stuff
-
-(when (require 'mumamo nil t)
-
-  (defun mumamo-chunk-jinja3(pos min max)
-    "Find {# ... #}.  Return range and `jinja-mode'.
-See `mumamo-find-possible-chunk' for POS, MIN and MAX."
-    (mumamo-find-possible-chunk pos min max
-                                'mumamo-search-bw-exc-start-jinja3
-                                'mumamo-search-bw-exc-end-jinja3
-                                'mumamo-search-fw-exc-start-jinja3
-                                'mumamo-search-fw-exc-end-jinja3))
-
-  (defun mumamo-chunk-ambari_jinja2(pos min max)
-    "Find {{ ... }}.  Return range and `jinja-mode'.
-See `mumamo-find-possible-chunk' for POS, MIN and MAX."
-    (mumamo-find-possible-chunk pos min max
-                                'mumamo-search-bw-exc-start-ambari_jinja2
-                                'mumamo-search-bw-exc-end-ambari_jinja2
-                                'mumamo-search-fw-exc-start-ambari_jinja2
-                                'mumamo-search-fw-exc-end-ambari_jinja2))
-
-  (defun mumamo-chunk-jinja (pos min max)
-    "Find {% ... %}.  Return range and `jinja-mode'.
-See `mumamo-find-possible-chunk' for POS, MIN and MAX."
-    (mumamo-find-possible-chunk pos min max
-                                'mumamo-search-bw-exc-start-jinja
-                                'mumamo-search-bw-exc-end-jinja
-                                'mumamo-search-fw-exc-start-jinja
-                                'mumamo-search-fw-exc-end-jinja))
-
-  (defun mumamo-search-bw-exc-start-jinja (pos min)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MIN is where to stop."
-    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{%")))
-      (and exc-start
-           (<= exc-start pos)
-           (cons exc-start 'jinja-mode))))
-
-  (defun mumamo-search-bw-exc-start-ambari_jinja2(pos min)
-    "Helper for `mumamo-chunk-ambari_jinja2'.
-POS is where to start search and MIN is where to stop."
-    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{{")))
-      (and exc-start
-           (<= exc-start pos)
-           (cons exc-start 'jinja-mode))))
-
-  (defun mumamo-search-bw-exc-start-jinja3(pos min)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MIN is where to stop."
-    (let ((exc-start (mumamo-chunk-start-bw-str-inc pos min "{#")))
-      (and exc-start
-           (<= exc-start pos)
-           (cons exc-start 'jinja-mode))))
-
-  (defun mumamo-search-bw-exc-end-jinja (pos min)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MIN is where to stop."
-    (mumamo-chunk-end-bw-str-inc pos min "%}"))
-
-  (defun mumamo-search-bw-exc-end-ambari_jinja2(pos min)
-    "Helper for `mumamo-chunk-ambari_jinja2'.
-POS is where to start search and MIN is where to stop."
-    (mumamo-chunk-end-bw-str-inc pos min "}}"))
-
-  (defun mumamo-search-bw-exc-end-jinja3(pos min)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MIN is where to stop."
-    (mumamo-chunk-end-bw-str-inc pos min "#}"))
-
-  (defun mumamo-search-fw-exc-start-jinja (pos max)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-start-fw-str-inc pos max "{%"))
-
-  (defun mumamo-search-fw-exc-start-ambari_jinja2(pos max)
-    "Helper for `mumamo-chunk-ambari_jinja2'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-start-fw-str-inc pos max "{{"))
-
-  (defun mumamo-search-fw-exc-start-jinja3(pos max)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-start-fw-str-inc pos max "{#"))
-
-  (defun mumamo-search-fw-exc-end-jinja (pos max)
-    "Helper for `mumamo-chunk-jinja'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-end-fw-str-inc pos max "%}"))
-
-  (defun mumamo-search-fw-exc-end-ambari_jinja2(pos max)
-    "Helper for `mumamo-chunk-ambari_jinja2'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-end-fw-str-inc pos max "}}"))
-
-  (defun mumamo-search-fw-exc-end-jinja3(pos max)
-    "Helper for `mumamo-chunk-jinja3'.
-POS is where to start search and MAX is where to stop."
-    (mumamo-chunk-end-fw-str-inc pos max "#}"))
-
-;;;###autoload
-  (define-mumamo-multi-major-mode jinja-html-mumamo
-    "Turn on multiple major modes for Jinja with main mode `html-mode'.
-This also covers inlined style and javascript."
-    ("Jinja HTML Family" html-mode
-     (mumamo-chunk-jinja
-      mumamo-chunk-ambari_jinja2
-      mumamo-chunk-jinja3
-      mumamo-chunk-inlined-style
-      mumamo-chunk-inlined-script
-      mumamo-chunk-style=
-      mumamo-chunk-onjs=
-      )))
-
-;;;###autoload
-  (define-mumamo-multi-major-mode jinja-nxhtml-mumamo
-    "Turn on multiple major modes for Jinja with main mode `nxhtml-mode'.
-This also covers inlined style and javascript."
-    ("Jinja nXhtml Family" nxhtml-mode
-     (mumamo-chunk-jinja
-      mumamo-chunk-ambari_jinja2
-      mumamo-chunk-jinja3
-      mumamo-chunk-inlined-style
-      mumamo-chunk-inlined-script
-      mumamo-chunk-style=
-      mumamo-chunk-onjs=
-      )))
-  )
-
-(provide 'jinja)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; jinja.el ends here

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py b/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py
deleted file mode 100644
index f8d5571..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/jinja2-debug.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-    Jinja2 Debug Interface
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Helper script for internal Jinja2 debugging.  Requires Werkzeug.
-
-    :copyright: Copyright 2010 by Armin Ronacher.
-    :license: BSD.
-"""
-import sys
-import ambari_jinja2
-from werkzeug import script
-
-env = ambari_jinja2.Environment(extensions=['ambari_jinja2.ext.i18n', 'ambari_jinja2.ext.do',
-                                     'ambari_jinja2.ext.loopcontrols'])
-
-def shell_init_func():
-    def _compile(x):
-        print env.compile(x, raw=True)
-    result = {
-        'e':        env,
-        'c':        _compile,
-        't':        env.from_string,
-        'p':        env.parse
-    }
-    for key in ambari_jinja2.__all__:
-        result[key] = getattr(ambari_jinja2, key)
-    return result
-
-
-def action_compile():
-    print env.compile(sys.stdin.read(), raw=True)
-
-action_shell = script.make_shell(shell_init_func)
-
-
-if __name__ == '__main__':
-    script.run()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc b/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc
deleted file mode 100644
index 4f85b49..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/scripts/pylintrc
+++ /dev/null
@@ -1,301 +0,0 @@
-# lint Python modules using external checkers.
-# 
-# This is the main checker controling the other ones and the reports
-# generation. It is itself both a raw checker and an astng checker in order
-# to:
-# * handle message activation / deactivation at the module level
-# * handle some basic but necessary stats'data (number of classes, methods...)
-# 
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Profiled execution.
-profile=no
-
-# Add <file or directory> to the black list. It should be a base name, not a
-# path. You may set this option multiple times.
-ignore=.svn
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# Set the cache size for astng objects.
-cache-size=500
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
-[MESSAGES CONTROL]
-
-# Enable only checker(s) with the given id(s). This option conflict with the
-# disable-checker option
-#enable-checker=
-
-# Enable all checker(s) except those with the given id(s). This option conflict
-# with the disable-checker option
-#disable-checker=
-
-# Enable all messages in the listed categories.
-#enable-msg-cat=
-
-# Disable all messages in the listed categories.
-#disable-msg-cat=
-
-# Enable the message(s) with the given id(s).
-#enable-msg=
-
-# Disable the message(s) with the given id(s).
-disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201
-
-
-[REPORTS]
-
-# set the output format. Available formats are text, parseable, colorized and
-# html
-output-format=colorized
-
-# Include message's id in output
-include-ids=yes
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells wether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note).You have access to the variables errors warning, statement which
-# respectivly contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (R0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (R0004).
-comment=no
-
-# Enable the report(s) with the given id(s).
-#enable-report=
-
-# Disable the report(s) with the given id(s).
-#disable-report=
-
-
-# checks for
-# * unused variables / imports
-# * undefined variables
-# * redefinition of variable from builtins or from an outer scope
-# * use of variable before assigment
-# 
-[VARIABLES]
-
-# Tells wether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching names used for dummy variables (i.e. not used).
-dummy-variables-rgx=_|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-
-# try to find bugs in the code using type inference
-# 
-[TYPECHECK]
-
-# Tells wether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# When zope mode is activated, consider the acquired-members option to ignore
-# access to some undefined attributes.
-zope=no
-
-# List of members which are usually get through zope's acquisition mecanism and
-# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
-acquired-members=REQUEST,acl_users,aq_parent
-
-
-# checks for :
-# * doc strings
-# * modules / classes / functions / methods / arguments / variables name
-# * number of arguments, local variables, branchs, returns and statements in
-# functions, methods
-# * required module attributes
-# * dangerous default values as arguments
-# * redefinition of function / method / class
-# * uses of the global statement
-# 
-[BASIC]
-
-# Required attributes for module, separated by a comma
-required-attributes=
-
-# Regular expression which should only match functions or classes name which do
-# not require a docstring
-no-docstring-rgx=__.*__
-
-# Regular expression which should only match correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression which should only match correct module level names
-const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
-
-# Regular expression which should only match correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression which should only match correct function names
-function-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct method names
-method-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct instance attribute names
-attr-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct argument names
-argument-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct variable names
-variable-rgx=[a-z_][a-z0-9_]*$
-
-# Regular expression which should only match correct list comprehension /
-# generator expression variable names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=apply,input
-
-
-# checks for sign of poor/misdesign:
-# * number of methods, attributes, local variables...
-# * size, complexity of functions, methods
-# 
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=12
-
-# Maximum number of locals for function / method body
-max-locals=30
-
-# Maximum number of return / yield for function / method body
-max-returns=12
-
-# Maximum number of branch for function / method body
-max-branchs=30
-
-# Maximum number of statements in function / method body
-max-statements=60
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=20
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=0
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-# checks for
-# * external modules dependencies
-# * relative / wildcard imports
-# * cyclic imports
-# * uses of deprecated modules
-# 
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report R0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report R0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report R0402 must
-# not be disabled)
-int-import-graph=
-
-
-# checks for :
-# * methods without self as first argument
-# * overridden methods signature
-# * access only to existant members via self
-# * attributes not defined in the __init__ method
-# * supported interfaces implementation
-# * unreachable code
-# 
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-
-# checks for similarities and duplicated code. This computation may be
-# memory / CPU intensive, so you should disable it if you experiments some
-# problems.
-# 
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=10
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-
-# checks for:
-# * warning notes in the code like FIXME, XXX
-# * PEP 263: source code with non ascii character but no encoding declaration
-# 
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-# checks for :
-# * unauthorized constructions
-# * strict indentation
-# * line length
-# * use of <> instead of !=
-# 
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=90
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string='    '

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/setup.cfg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/setup.cfg b/ambari-common/src/main/python/ambari_jinja2/setup.cfg
deleted file mode 100644
index 2d74c58..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/setup.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-[egg_info]
-tag_build = dev
-tag_date = true
-
-[aliases]
-release = egg_info -RDb ''

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/setup.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/setup.py b/ambari-common/src/main/python/ambari_jinja2/setup.py
deleted file mode 100644
index 7a7c242..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/setup.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Jinja2
-~~~~~~
-
-Jinja2 is a template engine written in pure Python.  It provides a
-`Django`_ inspired non-XML syntax but supports inline expressions and
-an optional `sandboxed`_ environment.
-
-Nutshell
---------
-
-Here a small example of a Jinja template::
-
-    {% extends 'base.html' %}
-    {% block title %}Memberlist{% endblock %}
-    {% block content %}
-      <ul>
-      {% for user in users %}
-        <li><a href="{{ user.url }}">{{ user.username }}</a></li>
-      {% endfor %}
-      </ul>
-    {% endblock %}
-
-Philosophy
-----------
-
-Application logic is for the controller but don't try to make the life
-for the template designer too hard by giving him too few functionality.
-
-For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
-
-.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security)
-.. _Django: http://www.djangoproject.com/
-.. _Jinja2 webpage: http://jinja.pocoo.org/
-.. _documentation: http://jinja.pocoo.org/2/documentation/
-"""
-import sys
-
-from setuptools import setup, Extension, Feature
-
-debugsupport = Feature(
-    'optional C debug support',
-    standard=False,
-    ext_modules = [
-        Extension('ambari_jinja2._debugsupport', ['ambari_jinja2/_debugsupport.c']),
-    ],
-)
-
-
-# tell distribute to use 2to3 with our own fixers.
-extra = {}
-if sys.version_info >= (3, 0):
-    extra.update(
-        use_2to3=True,
-        use_2to3_fixers=['custom_fixers']
-    )
-
-# ignore the old '--with-speedups' flag
-try:
-    speedups_pos = sys.argv.index('--with-speedups')
-except ValueError:
-    pass
-else:
-    sys.argv[speedups_pos] = '--with-debugsupport'
-    sys.stderr.write('*' * 74 + '\n')
-    sys.stderr.write('WARNING:\n')
-    sys.stderr.write('  the --with-speedups flag is deprecated, assuming '
-                     '--with-debugsupport\n')
-    sys.stderr.write('  For the actual speedups install the MarkupSafe '
-                     'package.\n')
-    sys.stderr.write('*' * 74 + '\n')
-
-
-setup(
-    name='Jinja2',
-    version='2.5.5',
-    url='http://jinja.pocoo.org/',
-    license='BSD',
-    author='Armin Ronacher',
-    author_email='armin.ronacher@active-4.com',
-    description='A small but fast and easy to use stand-alone template '
-                'engine written in pure python.',
-    long_description=__doc__,
-    # jinja is egg safe. But we hate eggs
-    zip_safe=False,
-    classifiers=[
-        'Development Status :: 5 - Production/Stable',
-        'Environment :: Web Environment',
-        'Intended Audience :: Developers',
-        'License :: OSI Approved :: BSD License',
-        'Operating System :: OS Independent',
-        'Programming Language :: Python',
-        'Programming Language :: Python :: 3',
-        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
-        'Topic :: Software Development :: Libraries :: Python Modules',
-        'Topic :: Text Processing :: Markup :: HTML'
-    ],
-    packages=['ambari_jinja2', 'ambari_jinja2.testsuite', 'ambari_jinja2.testsuite.res',
-              'ambari_jinja2._markupsafe'],
-    extras_require={'i18n': ['Babel>=0.8']},
-    test_suite='ambari_jinja2.testsuite.suite',
-    include_package_data=True,
-    entry_points="""
-    [babel.extractors]
-    ambari_jinja2 = ambari_jinja2.ext:babel_extract[i18n]
-    """,
-    features={'debugsupport': debugsupport},
-    **extra
-)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/AUTHORS
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/AUTHORS b/ambari-common/src/main/python/jinja2/AUTHORS
new file mode 100644
index 0000000..c6cd9ba
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/AUTHORS
@@ -0,0 +1,31 @@
+Jinja is written and maintained by the Jinja Team and various
+contributors:
+
+Lead Developer:
+
+- Armin Ronacher <ar...@active-4.com>
+
+Developers:
+
+- Christoph Hack
+- Georg Brandl
+
+Contributors:
+
+- Bryan McLemore
+- Mickaël Guérin <ka...@crocobox.org>
+- Cameron Knight
+- Lawrence Journal-World.
+- David Cramer
+
+Patches and suggestions:
+
+- Ronny Pfannschmidt
+- Axel Böhm
+- Alexey Melchakov
+- Bryan McLemore
+- Clovis Fabricio (nosklo)
+- Cameron Knight
+- Peter van Dijk (Habbie)
+- Stefan Ebner
+- Rene Leonhardt

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/CHANGES
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/CHANGES b/ambari-common/src/main/python/jinja2/CHANGES
new file mode 100644
index 0000000..2a49c64
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/CHANGES
@@ -0,0 +1,235 @@
+Jinja2 Changelog
+================
+
+Version 2.5.5
+-------------
+(re-release of 2.5.4 with built documentation removed for filesize.
+ Released on October 18th 2010)
+
+- built documentation is no longer part of release.
+
+Version 2.5.4
+-------------
+(bugfix release, released on October 17th 2010)
+
+- Fixed extensions not loading properly with overlays.
+- Work around a bug in cpython for the debugger that causes segfaults
+  on 64bit big-endian architectures.
+
+Version 2.5.3
+-------------
+(bugfix release, released on October 17th 2010)
+
+- fixed an operator precedence error introduced in 2.5.2.  Statements
+  like "-foo.bar" had their implicit parentheses applied around the
+  first part of the expression ("(-foo).bar") instead of the more
+  correct "-(foo.bar)".
+
+Version 2.5.2
+-------------
+(bugfix release, released on August 18th 2010)
+
+- improved setup.py script to better work with assumptions people
+  might still have from it (``--with-speedups``).
+- fixed a packaging error that excluded the new debug support.
+
+Version 2.5.1
+-------------
+(bugfix release, released on August 17th 2010)
+
+- StopIteration exceptions raised by functions called from templates
+  are now intercepted and converted to undefineds.  This solves a
+  lot of debugging grief.  (StopIteration is used internally to
+  abort template execution)
+- improved performance of macro calls slightly.
+- babel extraction can now properly extract newstyle gettext calls.
+- using the variable `num` in newstyle gettext for something else
+  than the pluralize count will no longer raise a :exc:`KeyError`.
+- removed builtin markup class and switched to markupsafe.  For backwards
+  compatibility the pure Python implementation still exists but is
+  pulled from markupsafe by the Jinja2 developers.  The debug support
+  went into a separate feature called "debugsupport" and is disabled
+  by default because it is only relevant for Python 2.4
+- fixed an issue with unary operators having the wrong precendence.
+
+Version 2.5
+-----------
+(codename Incoherence, relased on May 29th 2010)
+
+- improved the sort filter (should have worked like this for a
+  long time) by adding support for case insensitive searches.
+- fixed a bug for getattribute constant folding.
+- support for newstyle gettext translations which result in a
+  nicer in-template user interface and more consistent
+  catalogs. (:ref:`newstyle-gettext`)
+- it's now possible to register extensions after an environment
+  was created.
+
+Version 2.4.1
+-------------
+(bugfix release, released on April 20th 2010)
+
+- fixed an error reporting bug for undefineds.
+
+Version 2.4
+-----------
+(codename Correlation, released on April 13th 2010)
+
+- the environment template loading functions now transparently
+  pass through a template object if it was passed to it.  This
+  makes it possible to import or extend from a template object
+  that was passed to the template.
+- added a :class:`ModuleLoader` that can load templates from
+  precompiled sources.  The environment now features a method
+  to compile the templates from a configured loader into a zip
+  file or folder.
+- the _speedups C extension now supports Python 3.
+- added support for autoescaping toggling sections and support
+  for evaluation contexts (:ref:`eval-context`).
+- extensions have a priority now.
+
+Version 2.3.1
+-------------
+(bugfix release, released on February 19th 2010)
+
+- fixed an error reporting bug on all python versions
+- fixed an error reporting bug on Python 2.4
+
+Version 2.3
+-----------
+(3000 Pythons, released on February 10th 2010)
+
+- fixes issue with code generator that causes unbound variables
+  to be generated if set was used in if-blocks and other small
+  identifier problems.
+- include tags are now able to select between multiple templates
+  and take the first that exists, if a list of templates is
+  given.
+- fixed a problem with having call blocks in outer scopes that
+  have an argument that is also used as local variable in an
+  inner frame (#360).
+- greatly improved error message reporting (#339)
+- implicit tuple expressions can no longer be totally empty.
+  This change makes ``{% if %}...{% endif %}`` a syntax error
+  now. (#364)
+- added support for translator comments if extracted via babel.
+- added with-statement extension.
+- experimental Python 3 support.
+
+Version 2.2.1
+-------------
+(bugfix release, released on September 14th 2009)
+
+- fixes some smaller problems for Jinja2 on Jython.
+
+Version 2.2
+-----------
+(codename Kong, released on September 13th 2009)
+
+- Include statements can now be marked with ``ignore missing`` to skip
+  non existing templates.
+- Priority of `not` raised.  It's now possible to write `not foo in bar`
+  as an alias to `foo not in bar` like in python.  Previously the grammar
+  required parentheses (`not (foo in bar)`) which was odd.
+- Fixed a bug that caused syntax errors when defining macros or using the
+  `{% call %}` tag inside loops.
+- Fixed a bug in the parser that made ``{{ foo[1, 2] }}`` impossible.
+- Made it possible to refer to names from outer scopes in included templates
+  that were unused in the callers frame (#327)
+- Fixed a bug that caused internal errors if names where used as iteration
+  variable and regular variable *after* the loop if that variable was unused
+  *before* the loop.  (#331)
+- Added support for optional `scoped` modifier to blocks.
+- Added support for line-comments.
+- Added the `meta` module.
+- Renamed (undocumented) attribute "overlay" to "overlayed" on the
+  environment because it was clashing with a method of the same name.
+- speedup extension is now disabled by default.
+
+Version 2.1.1
+-------------
+(Bugfix release)
+
+- Fixed a translation error caused by looping over empty recursive loops.
+
+Version 2.1
+-----------
+(codename Yasuzō, released on November 23rd 2008)
+
+- fixed a bug with nested loops and the special loop variable.  Before the
+  change an inner loop overwrote the loop variable from the outer one after
+  iteration.
+
+- fixed a bug with the i18n extension that caused the explicit pluralization
+  block to look up the wrong variable.
+
+- fixed a limitation in the lexer that made ``{{ foo.0.0 }}`` impossible.
+
+- index based subscribing of variables with a constant value returns an
+  undefined object now instead of raising an index error.  This was a bug
+  caused by eager optimizing.
+
+- the i18n extension looks up `foo.ugettext` now followed by `foo.gettext`
+  if an translations object is installed.  This makes dealing with custom
+  translations classes easier.
+
+- fixed a confusing behavior with conditional extending.  loops were partially
+  executed under some conditions even though they were not part of a visible
+  area.
+
+- added `sort` filter that works like `dictsort` but for arbitrary sequences.
+
+- fixed a bug with empty statements in macros.
+
+- implemented a bytecode cache system.  (:ref:`bytecode-cache`)
+
+- the template context is now weakref-able
+
+- inclusions and imports "with context" forward all variables now, not only
+  the initial context.
+
+- added a cycle helper called `cycler`.
+
+- added a joining helper called `joiner`.
+
+- added a `compile_expression` method to the environment that allows compiling
+  of Jinja expressions into callable Python objects.
+
+- fixed an escaping bug in urlize
+
+Version 2.0
+-----------
+(codename jinjavitus, released on July 17th 2008)
+
+- the subscribing of objects (looking up attributes and items) changed from
+  slightly.  It's now possible to give attributes or items a higher priority
+  by either using dot-notation lookup or the bracket syntax.  This also
+  changed the AST slightly.  `Subscript` is gone and was replaced with
+  :class:`~jinja2.nodes.Getitem` and :class:`~jinja2.nodes.Getattr`.
+
+  For more information see :ref:`the implementation details <notes-on-subscriptions>`.
+
+- added support for preprocessing and token stream filtering for extensions.
+  This would allow extensions to allow simplified gettext calls in template
+  data and something similar.
+
+- added :meth:`jinja2.environment.TemplateStream.dump`.
+
+- added missing support for implicit string literal concatenation.
+  ``{{ "foo" "bar" }}`` is equivalent to ``{{ "foobar" }}``
+
+- `else` is optional for conditional expressions.  If not given it evaluates
+  to `false`.
+
+- improved error reporting for undefined values by providing a position.
+
+- `filesizeformat` filter uses decimal prefixes now per default and can be
+  set to binary mode with the second parameter.
+
+- fixed bug in finalizer
+
+Version 2.0rc1
+--------------
+(no codename, released on June 9th 2008)
+
+- first release of Jinja2

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/LICENSE
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/LICENSE b/ambari-common/src/main/python/jinja2/LICENSE
new file mode 100644
index 0000000..31bf900
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of the contributors may not be used to endorse or
+      promote products derived from this software without specific
+      prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/MANIFEST.in
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/MANIFEST.in b/ambari-common/src/main/python/jinja2/MANIFEST.in
new file mode 100644
index 0000000..aeb66af
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/MANIFEST.in
@@ -0,0 +1,12 @@
+include MANIFEST.in Makefile CHANGES LICENSE AUTHORS jinja2/_debugsupport.c
+recursive-include docs *
+recursive-include custom_fixers *
+recursive-include ext *
+recursive-include artwork *
+recursive-include examples *
+recursive-include jinja2/testsuite/res *
+recursive-exclude docs/_build *
+recursive-exclude jinja2 *.pyc
+recursive-exclude docs *.pyc
+recursive-exclude jinja2 *.pyo
+recursive-exclude docs *.pyo

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/Makefile b/ambari-common/src/main/python/jinja2/Makefile
new file mode 100644
index 0000000..60ca1d7
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/Makefile
@@ -0,0 +1,4 @@
+test:
+	python setup.py test
+
+.PHONY: test

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg b/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg
new file mode 100644
index 0000000..0bc9ea4
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/artwork/jinjalogo.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="300"
+   height="120"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   version="1.0"
+   sodipodi:docbase="/Users/mitsuhiko/Development/jinja2/artwork"
+   sodipodi:docname="jinjalogo.svg"
+   inkscape:export-filename="/Users/mitsuhiko/Development/jinja2/docs/_static/jinjabanner.png"
+   inkscape:export-xdpi="60"
+   inkscape:export-ydpi="60"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient6558">
+      <stop
+         style="stop-color:#575757;stop-opacity:1;"
+         offset="0"
+         id="stop6560" />
+      <stop
+         style="stop-color:#2f2f2f;stop-opacity:1;"
+         offset="1"
+         id="stop6562" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="radialGradient6564"
+       cx="61.297766"
+       cy="60.910986"
+       fx="61.297766"
+       fy="60.910986"
+       r="44.688254"
+       gradientTransform="matrix(1,0,0,0.945104,0,3.343747)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="radialGradient6580"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.945104,0.355158,3.334402)"
+       cx="61.297766"
+       cy="60.910986"
+       fx="61.297766"
+       fy="60.910986"
+       r="44.688254" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="linearGradient4173"
+       x1="255.15521"
+       y1="32.347946"
+       x2="279.8912"
+       y2="32.347946"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.8073249,0,0,0.8073249,57.960878,7.4036303)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="linearGradient5145"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.7902775,0,0,0.82474,60.019977,8.0684132)"
+       x1="255.15521"
+       y1="32.347946"
+       x2="279.8912"
+       y2="32.347946" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8"
+     inkscape:cx="137.4752"
+     inkscape:cy="57.574575"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="300px"
+     height="120px"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1396"
+     inkscape:window-height="900"
+     inkscape:window-x="0"
+     inkscape:window-y="22" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#f4f4f4;fill-opacity:1;stroke:#e7e7e7;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;font-family:Bitstream Vera Sans;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 165.36463,80.874808 L 165.36463,80.874808 L 153.32556,80.874808 L 153.32556,81.8344 L 147.64994,81.8344 L 147.64994,36.035583 L 165.36463,36.035583 L 165.36463,20.333129 C 170.58154,21.031083 173.07533,22.077914 172.84609,23.473621 C 172.78871,24.055258 172.21545,24.549594 171.12624,24.956624 L 171.12624,36.035583 L 189.09895,36.035583 L 189.09895,82.532286 L 183.33733,82.532286 L 183.33733,80.874808 L 171.12624,80.874808 L 171.12624,102.94548 L 165.36463,102.94548 L 165.36463,80.874808 M 153.32556,55.489173 L 153.32556,55.489173 L 165.36463,55.489173 L 165.36463,41.793146 L 153.32556,41.793146 L 153.32556,55.489173 M 171.12624,55.489173 L 171.12624,55.489173 L 183.33733,55.489173 L 183.33733,41.793146 L 171.12624,41.793146 L 171.12624,55.489173 M 183.33733,61.333977 L 183.33733,61.333977 L 171.12624,61.333977 L 171.12624,75.030006 L 183.33733,75.030006 L 183.33733,61.333977 M 165.36463,61.333977 L 165.36463,61.333977 L 153.32556,61.333977 L 153.32556,75.030006 L 165.364
 63,75.030006 L 165.36463,61.333977 M 132.85897,59.414792 C 137.33069,63.136883 140.99969,67.934848 143.86618,73.808701 L 139.13654,77.385372 C 137.24467,72.965445 134.6362,69.12707 131.31114,65.87024 L 131.31114,102.94548 L 125.63554,102.94548 L 125.63554,68.57455 C 122.31042,71.947693 118.52671,74.913707 114.28436,77.47261 L 109.64069,73.372526 C 121.50782,67.091566 130.62312,55.489212 136.98668,38.565417 L 116.26221,38.565417 L 116.26221,32.720615 L 125.80754,32.720615 L 125.80754,20.333129 C 130.85245,21.031083 133.31761,22.048838 133.20299,23.386383 C 133.14561,24.026183 132.57235,24.549594 131.48307,24.956624 L 131.48307,32.720615 L 140.77043,32.720615 L 143.60824,36.733469 C 140.68444,45.51526 137.10137,53.075692 132.85897,59.414792 M 254.11016,49.469901 L 254.11016,49.469901 L 254.11016,20.333129 C 259.21243,21.031083 261.67755,22.048838 261.50562,23.386383 C 261.44823,23.909869 261.04699,24.346044 260.30172,24.694917 C 260.30164,24.694986 260.30164,24.694986 260.30172,24.694
 917 L 260.30172,24.694917 L 259.78578,24.956624 L 259.78578,49.469901 L 277.15652,49.469901 L 277.15652,55.227471 L 259.78578,55.227471 L 259.78578,93.785712 L 281.45616,93.785712 L 281.45616,99.63051 L 232.35378,99.63051 L 232.35378,93.785712 L 254.11016,93.785712 L 254.11016,55.227471 L 236.22346,55.227471 L 236.22346,49.469901 L 254.11016,49.469901 M 225.5603,59.327554 C 231.12111,63.107798 235.62145,67.876693 239.06127,73.634235 L 234.76157,77.647079 C 231.60845,72.180322 227.82475,67.934848 223.41044,64.910648 L 223.41044,102.94548 L 217.73484,102.94548 L 217.73484,67.44049 C 212.91919,71.627831 207.70222,75.030021 202.084,77.647079 L 197.87027,73.198053 C 212.66118,66.917101 224.01239,55.372897 231.92377,38.565417 L 205.35172,38.565417 L 205.35172,32.720615 L 217.99283,32.720615 L 217.99283,20.333129 C 223.03774,21.031083 225.50291,22.048838 225.38829,23.386383 C 225.33089,24.026183 224.75765,24.549594 223.66837,24.956624 L 223.66837,32.720615 L 236.22346,32.720615 L 238.80326
 ,36.733469 C 235.13421,45.51526 230.71987,53.046611 225.5603,59.327554"
+       id="text4761" />
+    <path
+       style="font-size:44.09793472px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#b41717;fill-opacity:1;stroke:#7f2828;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Candara;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 149.14708,37.774469 C 148.97807,41.117899 148.84526,44.824225 148.74871,48.893456 C 148.67626,52.962754 148.3818,70.641328 148.38184,75.524422 C 148.3818,79.065795 148.05588,81.991266 147.40406,84.300835 C 146.75219,86.610422 145.72612,88.557071 144.32585,90.140779 C 142.94969,91.724494 141.17522,92.901283 139.00239,93.671139 C 136.82953,94.440996 134.22211,94.825935 131.18014,94.825935 C 128.83828,94.825935 126.73787,94.59498 124.87889,94.133049 L 125.4221,89.31593 C 127.13623,90.0418 128.92278,90.404734 130.78177,90.404733 C 132.85805,90.404734 134.66875,90.140782 136.2139,89.612876 C 137.78315,89.062981 139.02651,88.216133 139.94396,87.072335 C 140.8855,85.928548 141.54942,84.520804 141.93572,82.8491 C 142.34613,81.177412 142.55134,78.988811 142.55136,76.283285 C 142.55134,66.297119 142.62852,44.659257 142.26641,37.774469 L 149.14708,37.774469 M 166.38498,80.732697 L 159.83024,80.732697 C 160.16821,76.333498 160.33723,71.307412 160.33723,65.654424 C 160.33723,59.2976 
 159.91471,53.963567 159.06973,49.652319 L 166.31257,48.761483 C 166.02284,53.358679 165.87799,58.98965 165.87799,65.654424 C 165.87799,70.933479 166.04699,75.959565 166.38498,80.732697 M 167.90601,39.490159 C 167.90598,40.611994 167.5076,41.590815 166.7109,42.42662 C 165.91418,43.240515 164.79155,43.647442 163.343,43.647399 C 162.11172,43.647442 161.146,43.295504 160.44588,42.591595 C 159.76988,41.865769 159.43188,40.996927 159.43188,39.98507 C 159.43188,38.885304 159.84231,37.928485 160.66315,37.114591 C 161.48399,36.30078 162.61869,35.893853 164.06727,35.893811 C 165.25023,35.893853 166.17975,36.256783 166.85575,36.982609 C 167.55588,37.686526 167.90598,38.522373 167.90601,39.490159 M 206.72748,80.732697 L 200.13651,80.732697 C 200.66763,74.947749 200.93319,68.634899 200.9332,61.794122 C 200.93319,58.406756 200.1727,56.097177 198.65174,54.865371 C 197.15487,53.61163 195.00619,52.984747 192.20564,52.984714 C 188.77731,52.984747 185.61465,54.117535 182.71753,56.383099 C 182.71753,63
 .883761 182.76583,72.000287 182.86238,80.732697 L 176.27142,80.732697 C 176.68182,73.254058 176.88707,67.843042 176.88707,64.499632 C 176.88707,59.352589 176.3559,54.359493 175.29363,49.520339 L 181.66734,48.695493 L 182.35539,52.720761 L 182.64511,52.720761 C 186.21823,49.773323 190.04483,48.299592 194.12499,48.299567 C 198.13265,48.299592 201.23499,49.113454 203.43201,50.741118 C 205.62895,52.346863 206.72747,55.217334 206.72748,59.352563 C 206.72747,59.770507 206.70331,60.595362 206.65507,61.827118 C 206.60675,63.058915 206.5826,63.883761 206.58262,64.30167 C 206.5826,67.975018 206.63088,73.452022 206.72748,80.732697 M 222.69791,48.695493 C 222.28747,55.514282 222.08225,62.355041 222.08225,69.21778 C 222.08225,71.043461 222.14262,73.463019 222.26332,76.476468 C 222.40822,79.467925 222.4806,81.502559 222.48063,82.580363 C 222.4806,89.685068 219.51105,93.996287 213.57195,95.514024 L 211.76124,93.006484 C 213.90995,91.356766 215.2378,89.597085 215.74478,87.727431 C 216.49321,85.0439
 12 216.86743,79.324953 216.86743,70.570535 C 216.86743,61.178248 216.3846,54.16153 215.41887,49.520339 L 222.69791,48.695493 M 224.2551,39.490159 C 224.2551,40.611994 223.85673,41.590815 223.06006,42.42662 C 222.26332,43.240515 221.14069,43.647442 219.69213,43.647399 C 218.46084,43.647442 217.49515,43.295504 216.795,42.591595 C 216.119,41.865769 215.781,40.996927 215.781,39.98507 C 215.781,38.885304 216.19144,37.928485 217.01231,37.114591 C 217.83316,36.30078 218.96785,35.893853 220.4164,35.893811 C 221.5994,35.893853 222.52889,36.256783 223.20492,36.982609 C 223.90503,37.686526 224.2551,38.522373 224.2551,39.490159 M 259.60008,80.732697 L 253.91446,80.930661 C 253.62473,79.852857 253.47987,78.830045 253.4799,77.862216 L 253.11774,77.862216 C 250.14817,80.325772 246.10427,81.557546 240.98606,81.557547 C 238.20962,81.557546 235.8195,80.820682 233.81563,79.346948 C 231.81178,77.851221 230.80988,75.728607 230.80988,72.979099 C 230.80988,69.591724 232.37914,66.875216 235.51769,64.829574
  C 238.65625,62.761967 244.48667,61.67316 253.00913,61.563165 C 253.08155,61.035275 253.11772,60.430386 253.11774,59.748497 C 253.11772,57.043003 252.32104,55.239336 250.72765,54.337474 C 249.15832,53.435661 246.76819,52.984747 243.55721,52.984714 C 239.76681,52.984747 236.03678,53.413668 232.3671,54.271484 L 232.9827,49.718301 C 236.60411,48.77251 240.76873,48.299592 245.47658,48.299567 C 249.77395,48.299592 253.09359,49.113454 255.43545,50.741118 C 257.77728,52.346863 258.94819,55.096363 258.94824,58.989625 C 258.94819,60.023469 258.88785,61.904117 258.76715,64.631608 C 258.67054,67.337133 258.62228,69.140806 258.6223,70.042632 C 258.62228,74.045913 258.94819,77.609265 259.60008,80.732697 M 253.19019,74.331856 C 253.06945,70.988469 253.00909,67.986016 253.00913,65.324484 C 248.47027,65.324498 245.01786,65.632443 242.65187,66.248318 C 238.69248,67.348131 236.71278,69.448748 236.71278,72.550177 C 236.71278,75.541643 239.03044,77.037371 243.66588,77.037366 C 247.64942,77.037371 250.8
 2416,76.135534 253.19019,74.331856"
+       id="text3736"
+       sodipodi:nodetypes="ccsscssccscccsccccsccsccsscsssccccscscccsccccscsssccscscccscccsscsssccccccscsccscsccscscsccccssc" />
+    <path
+       style="fill:url(#radialGradient6564);fill-opacity:1.0;fill-rule:evenodd;stroke:#323232;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 105.45673,18.675923 C 105.45673,18.675923 88.211949,26.918461 74.172834,28.737898 C 60.133727,30.557333 33.360434,32.377571 28.045622,31.093256 C 22.730818,29.808941 18.915645,28.309196 18.915645,28.309196 L 20.021441,32.056583 L 16.609513,35.052471 L 17.2144,36.121726 L 18.61792,36.22764 L 22.92773,36.762252 L 23.532621,38.688909 L 25.937975,38.905784 L 27.143021,42.970927 C 27.143021,42.970927 32.254764,43.399628 33.758953,43.399628 C 35.263142,43.399628 38.271966,43.187802 38.271966,43.187802 L 38.371202,44.791657 L 39.477002,45.003495 L 39.477002,46.824227 L 37.066917,48.967759 L 37.671807,49.073671 L 37.671807,49.820127 C 37.671807,49.820127 32.255457,50.252157 30.049301,49.93109 C 27.843157,49.610006 27.440747,49.608286 27.440747,49.608286 L 27.242258,49.820127 L 27.143021,50.783455 L 27.643946,50.783455 L 27.84242,54.959544 L 38.976091,54.530844 L 38.172728,68.980747 L 38.073481,70.796442 L 28.645781,70.261816 L 28.546544,66.408513 L 30.649462,66.408513 L 30.85267
 3,64.910557 L 32.757107,64.481857 L 33.059555,64.058192 L 25.937975,62.343374 L 20.522364,63.947229 L 21.42496,64.698732 L 22.327572,64.698732 L 22.426809,65.984848 L 24.331254,66.09076 L 24.331254,69.838147 L 22.228335,70.372777 L 22.630009,71.225146 L 23.130934,71.547931 L 23.130934,74.437917 L 24.435218,74.437917 L 24.435218,87.813529 L 22.327572,88.13632 L 22.630009,91.989617 L 23.929569,92.206492 L 23.731093,100.98236 L 29.449141,101.08826 L 28.244105,92.418334 L 36.868446,92.206492 L 36.268285,96.912181 L 35.464925,100.23086 L 44.188501,100.33677 L 44.287739,91.777793 L 50.303506,91.243181 L 50.005786,96.700351 L 49.802585,99.90807 L 54.920484,99.90807 L 54.717274,91.132217 L 55.421397,91.243181 L 55.619882,87.067076 L 54.816521,87.067076 L 54.518798,85.352258 L 54.017874,80.429702 L 54.216359,74.760706 L 55.31743,74.760706 L 55.31743,71.336105 L 53.913913,71.442015 L 54.117112,67.402096 L 55.747469,67.240708 L 55.823083,65.929374 L 56.749319,65.793192 L 57.699176,65.071956 L 
 51.985842,63.896802 L 46.31977,65.15265 L 46.872668,66.060507 L 47.47283,66.010066 L 48.172228,65.984848 L 48.299828,67.639144 L 49.878196,67.563497 L 49.906548,71.144447 L 43.111042,70.988097 L 43.337879,67.160002 L 43.559978,63.679927 L 43.559978,59.105378 L 43.763188,54.288748 L 57.373101,53.592733 L 73.567955,52.659674 L 73.71917,55.736265 L 73.142647,63.120082 L 72.892183,69.9945 L 66.928387,69.888585 L 66.900039,65.071956 L 69.106918,64.991267 L 69.206169,63.629486 L 70.108765,63.493308 L 70.061506,63.226006 L 70.964116,63.175568 L 71.465028,62.504773 L 64.721507,60.926122 L 58.001612,62.368592 L 58.4789,63.200785 L 59.230285,63.1453 L 59.230285,63.523577 L 60.156518,63.523577 L 60.156518,65.046738 L 62.136575,65.071956 L 62.112937,69.298485 L 60.109259,69.298485 L 60.080907,70.261816 L 60.785031,70.342507 L 60.70942,74.009202 L 62.188552,74.089909 L 62.013701,88.620507 L 60.057282,89.018952 L 60.080907,89.714967 L 60.761406,89.714967 L 60.761406,93.437137 L 61.886113,93.43713
 7 L 61.588391,98.52109 L 61.210343,102.95945 L 68.331912,103.14605 L 68.105084,99.29275 L 67.580538,96.085028 L 67.476575,93.300955 L 73.520696,93.195041 L 73.345845,97.502272 L 73.317494,102.05159 L 76.729426,102.3189 L 81.3653,102.1323 L 82.820807,101.70358 L 82.017437,99.26753 L 81.818959,95.439438 L 81.440912,92.710853 L 87.206218,92.499027 L 86.955759,95.842931 L 86.932133,101.08826 L 89.238253,101.30009 L 91.520751,101.24965 L 92.621828,100.90165 L 91.969693,95.923633 L 91.747577,92.176239 L 92.725793,92.070324 L 92.749427,88.726422 L 93.02352,88.670945 L 92.976244,87.949712 L 91.846823,87.949712 L 91.619996,85.488427 L 91.520751,74.811143 L 92.371377,74.785924 L 92.371377,71.280616 L 92.725793,71.336105 L 92.725793,70.640088 L 91.468773,70.529127 L 91.497126,66.463987 L 93.600043,66.277382 L 93.477182,64.910557 L 94.403419,64.829863 L 94.351424,64.562549 L 95.580099,63.947229 L 89.337489,62.69138 L 82.995657,63.977495 L 83.39733,64.723951 L 84.375543,64.643256 L 84.427528,64.
 966046 L 85.254515,64.966046 L 85.301775,66.569901 L 87.357445,66.544681 L 87.532293,70.478688 L 80.264217,70.423216 L 79.413593,64.512124 L 78.733106,61.380041 L 78.184923,55.761484 L 78.510996,52.473053 L 92.999878,51.373557 L 93.047136,46.476221 L 93.774891,46.289613 L 93.727651,45.543159 L 93.174743,45.220372 C 93.174629,45.220372 85.252181,46.395266 82.745197,46.66284 C 82.0389,46.738209 82.09239,46.733258 81.516524,46.79397 L 81.440912,45.886118 L 78.444837,44.317564 L 78.482644,42.491786 L 79.512842,42.461518 L 79.588444,39.949808 C 79.588444,39.949808 85.728225,39.546834 88.009582,39.0117 C 90.290937,38.476559 93.524432,37.942456 93.524432,37.942456 L 95.055545,33.79662 L 98.089437,32.913987 L 98.339888,32.217972 L 105.20628,30.316548 L 105.98602,29.676006 L 103.37744,23.976741 L 103.62792,22.690624 L 104.95584,21.994611 L 105.91041,19.079404 L 105.45673,18.675923 z M 72.466874,40.403728 L 72.429067,42.476654 L 73.983813,42.542211 L 73.884576,44.509221 L 70.836515,46.506487 
 L 70.647496,47.081457 L 71.876167,47.091543 L 71.866712,47.575729 L 62.552432,48.029652 L 62.613863,46.652742 L 63.039175,45.966809 L 63.067524,45.528025 L 63.07698,44.579832 L 63.341609,43.949374 L 63.440849,43.439982 L 63.440849,43.076841 L 63.842533,41.47297 L 72.466874,40.403728 z M 52.987688,42.168984 L 52.760853,43.561027 L 53.488599,44.418431 L 53.441349,45.916386 L 54.117112,46.960408 L 53.942262,48.191039 L 54.443185,48.912273 L 44.939872,49.2855 L 44.916247,48.967759 L 46.017333,48.831579 L 46.069307,48.428097 L 43.66394,47.121797 L 43.536351,45.03375 L 44.689411,44.978276 L 44.788661,42.72883 L 52.987688,42.168984 z M 67.051262,74.276518 L 72.81657,74.649742 L 72.618099,82.411833 L 73.36947,88.776857 L 67.254465,88.565018 L 67.051262,74.276518 z M 28.44258,74.599304 L 37.671807,75.078442 L 36.868446,80.429702 L 36.868446,84.928593 L 37.520583,87.440302 L 28.494569,87.869006 L 28.44258,74.599304 z M 87.508658,74.649742 L 87.508658,87.924488 L 81.644113,88.353194 L 81.44091
 2,81.342592 L 80.788764,74.811143 L 87.508658,74.649742 z M 43.087416,74.947312 L 49.906548,74.972531 L 49.977434,87.278902 L 43.611966,87.389863 L 43.285891,83.400379 L 43.262266,79.441156 L 43.087416,74.947312 z "
+       id="path4735" />
+  </g>
+</svg>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py b/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py
new file mode 100644
index 0000000..96a81c1
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/custom_fixers/fix_alt_unicode.py
@@ -0,0 +1,13 @@
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import Name, BlankLine
+
+
+class FixAltUnicode(fixer_base.BaseFix):
+    PATTERN = """
+    func=funcdef< 'def' name='__unicode__'
+                  parameters< '(' NAME ')' > any+ >
+    """
+
+    def transform(self, node, results):
+        name = results['name']
+        name.replace(Name('__str__', prefix=name.prefix))

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py b/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py
new file mode 100644
index 0000000..fd0ea68
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/custom_fixers/fix_broken_reraising.py
@@ -0,0 +1,21 @@
+from lib2to3 import fixer_base, pytree
+from lib2to3.fixer_util import Name, BlankLine, Name, Attr, ArgList
+
+
+class FixBrokenReraising(fixer_base.BaseFix):
+    PATTERN = """
+    raise_stmt< 'raise' any ',' val=any ',' tb=any >
+    """
+
+    # run before the broken 2to3 checker with the same goal
+    # tries to rewrite it with a rule that does not work out for jinja
+    run_order = 1
+
+    def transform(self, node, results):
+        tb = results['tb'].clone()
+        tb.prefix = ''
+        with_tb = Attr(results['val'].clone(), Name('with_traceback')) + \
+                  [ArgList([tb])]
+        new = pytree.Node(self.syms.simple_stmt, [Name("raise")] + with_tb)
+        new.prefix = node.prefix
+        return new

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py b/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py
new file mode 100644
index 0000000..5d35e50
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/custom_fixers/fix_xrange2.py
@@ -0,0 +1,11 @@
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import Name, BlankLine
+
+
+# whyever this is necessary..
+
+class FixXrange2(fixer_base.BaseFix):
+    PATTERN = "'xrange'"
+
+    def transform(self, node, results):
+        node.replace(Name('range', prefix=node.prefix))

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/Makefile b/ambari-common/src/main/python/jinja2/docs/Makefile
new file mode 100644
index 0000000..5e24ec1
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/Makefile
@@ -0,0 +1,75 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview over all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+
+clean:
+	-rm -rf _build/*
+
+html:
+	mkdir -p _build/html _build/doctrees
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+	@echo
+	@echo "Build finished. The HTML pages are in _build/html."
+
+pickle:
+	mkdir -p _build/pickle _build/doctrees
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files"
+
+json:
+	mkdir -p _build/json _build/doctrees
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
+	@echo
+	@echo "Build finished; now you can process the json files"
+
+web: pickle
+
+htmlhelp:
+	mkdir -p _build/htmlhelp _build/doctrees
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in _build/htmlhelp."
+
+latex:
+	mkdir -p _build/latex _build/doctrees
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in _build/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	mkdir -p _build/changes _build/doctrees
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
+	@echo
+	@echo "The overview file is in _build/changes."
+
+linkcheck:
+	mkdir -p _build/linkcheck _build/doctrees
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in _build/linkcheck/output.txt."

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_static/jinja.js
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/jinja.js b/ambari-common/src/main/python/jinja2/docs/_static/jinja.js
new file mode 100644
index 0000000..1c04218
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_static/jinja.js
@@ -0,0 +1,26 @@
+$(function() {
+
+  var
+    toc = $('#toc').show(),
+    items = $('#toc > ul').hide();
+
+  $('#toc h3')
+    .click(function() {
+      if (items.is(':visible')) {
+        items.animate({
+          height:     'hide',
+          opacity:    'hide'
+        }, 300, function() {
+          toc.removeClass('expandedtoc');
+        });
+      }
+      else {
+        items.animate({
+          height:     'show',
+          opacity:    'show'
+        }, 400);
+        toc.addClass('expandedtoc');
+      }
+    });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_static/print.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/print.css b/ambari-common/src/main/python/jinja2/docs/_static/print.css
new file mode 100644
index 0000000..fb633d8
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_static/print.css
@@ -0,0 +1,5 @@
+div.header, div.relnav, #toc { display: none; }
+#contentwrapper { padding: 0; margin: 0; border: none; }
+body { color: black; background-color: white; }
+div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
+div.footer a { text-decoration: none; }

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_static/style.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_static/style.css b/ambari-common/src/main/python/jinja2/docs/_static/style.css
new file mode 100644
index 0000000..a1c4d59
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_static/style.css
@@ -0,0 +1,390 @@
+body {
+    background-color: #222;
+    margin: 0;
+    padding: 0;
+    font-family: 'Georgia', serif;
+    font-size: 15px;
+    color: #eee;
+}
+
+div.footer {
+    border-top: 1px solid #111;
+    padding: 8px;
+    font-size: 11px;
+    text-align: center;
+    letter-spacing: 0.5px;
+}
+
+div.footer a {
+    color: #eee;
+}
+
+div.header {
+    margin: 0 -15px 0 -15px;
+    background: url(headerbg.png) repeat-x;
+    border-top: 6px solid #D20000;
+}
+
+div.relnav {
+    border-bottom: 1px solid #111;
+    background: url(navigation.png);
+    margin: 0 -15px 0 -15px;
+    padding: 2px 20px 0 28px;
+    line-height: 25px;
+    color: #aaa;
+    font-size: 12px;
+    text-align: center;
+}
+
+div.relnav a {
+    color: #eee;
+    font-weight: bold;
+    text-decoration: none;
+}
+
+div.relnav a:hover {
+    text-decoration: underline;
+}
+
+#content {
+    background-color: white;
+    color: #111;
+    border-bottom: 1px solid black;
+    background: url(watermark.png) center 0;
+    padding: 0 15px 0 15px;
+    margin: 0;
+}
+
+h1 {
+    margin: 0;
+    padding: 15px 0 0 0;
+}
+
+h1.heading {
+    margin: 0;
+    padding: 0;
+    height: 80px;
+}
+
+h1.heading:hover {
+    background: #222;
+}
+
+h1.heading a {
+    background: url(jinjabanner.png) no-repeat center 0;
+    display: block;
+    width: 100%;
+    height: 80px;
+}
+
+h1.heading a:focus {
+    -moz-outline: none;
+    outline: none;
+}
+
+h1.heading span {
+    display: none;
+}
+
+#jinjalogo {
+    background-image: url(jinjalogo.png);
+    background-repeat: no-repeat;
+    width: 400px;
+    height: 160px;
+}
+
+#contentwrapper {
+    max-width: 680px;
+    padding: 0 18px 20px 18px;
+    margin: 0 auto 0 auto;
+    border-right: 1px solid #eee;
+    border-left: 1px solid #eee;
+    background: url(watermark_blur.png) center -114px;
+}
+
+#contentwrapper h2,
+#contentwrapper h2 a {
+    color: #222;
+    font-size: 24px;
+    margin: 20px 0 0 0;
+}
+
+#contentwrapper h3,
+#contentwrapper h3 a {
+    color: #b41717;
+    font-size: 20px;
+    margin: 20px 0 0 0;
+}
+
+table.docutils {
+    border-collapse: collapse;
+    border: 2px solid #aaa;
+    margin: 0.5em 1.5em 0.5em 1.5em;
+}
+
+table.docutils td {
+    padding: 2px;
+    border: 1px solid #ddd;
+}
+
+p, li, dd, dt, blockquote {
+    color: #333;
+}
+
+blockquote {
+    margin: 10px 0 10px 20px;
+}
+
+p {
+    line-height: 20px;
+    margin-bottom: 0;
+    margin-top: 10px;
+}
+
+hr {
+    border-top: 1px solid #ccc;
+    border-bottom: 0;
+    border-right: 0;
+    border-left: 0;
+    margin-bottom: 10px;
+    margin-top: 20px;
+}
+
+dl {
+    margin-left: 10px;
+}
+
+li, dt {
+    margin-top: 5px;
+}
+
+dt {
+    font-weight: bold;
+    color: #000;
+}
+
+dd {
+    margin-top: 10px;
+    line-height: 20px;
+}
+
+th {
+    text-align: left;
+    padding: 3px;
+    background-color: #f2f2f2;
+}
+
+a {
+    color: #b41717;
+}
+
+a:hover {
+    color: #444;
+}
+
+pre {
+    background: #ededed url(metal.png);
+    border-top: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+    padding: 5px;
+    font-size: 13px;
+    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+}
+
+tt {
+    font-size: 13px;
+    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+    color: black;
+    padding: 1px 2px 1px 2px;
+    background-color: #fafafa;
+    border-bottom: 1px solid #eee;
+}
+
+a.reference:hover tt {
+    border-bottom-color: #aaa;
+}
+
+cite {
+    /* abusing <cite>, it's generated by ReST for `x` */
+    font-size: 13px;
+    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+    font-weight: bold;
+    font-style: normal;
+}
+
+div.admonition {
+    margin: 10px 0 10px 0;
+    padding: 10px 10px 10px 60px;
+    border: 1px solid #ccc;
+}
+
+div.admonition p.admonition-title {
+    background-color: #b41717;
+    color: white;
+    margin: -10px -10px 10px -60px;
+    padding: 4px 10px 4px 10px;
+    font-weight: bold;
+    font-size: 15px;
+}
+
+div.admonition p.admonition-title a {
+    color: white!important;
+}
+
+div.admonition-note {
+    background: url(note.png) no-repeat 10px 40px;
+}
+
+div.admonition-implementation {
+    background: url(implementation.png) no-repeat 10px 40px;
+}
+
+a.headerlink {
+    color: #B4B4B4!important;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none!important;
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+dt:hover > a.headerlink {
+    visibility: visible;
+}
+
+a.headerlink:hover {
+    background-color: #B4B4B4;
+    color: #F0F0F0!important;
+}
+
+table.indextable {
+    width: 100%;
+}
+
+table.indextable td {
+    vertical-align: top;
+    width: 50%;
+}
+
+table.indextable dl dd {
+    font-size: 11px;
+}
+
+table.indextable dl dd a {
+    color: #000;
+}
+
+dl.function dt,
+dl.class dt,
+dl.exception dt,
+dl.method dt,
+dl.attribute dt {
+    font-weight: normal;
+}
+
+dt .descname {
+    font-weight: bold;
+    margin-right: 4px;
+}
+
+dt .descname, dt .descclassname {
+    padding: 0;
+    background: transparent;
+    border-bottom: 1px solid #111;
+}
+
+dt .descclassname {
+    margin-left: 2px;
+}
+
+dl dt big {
+    font-size: 100%;
+}
+
+ul.search {
+    margin: 10px 0 0 30px;
+    padding: 0;
+}
+
+ul.search li {
+    margin: 10px 0 0 0;
+    padding: 0;
+}
+
+ul.search div.context {
+    font-size: 12px;
+    padding: 4px 0 0 20px;
+    color: #888;
+}
+
+span.highlight {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+#toc {
+    margin: 0 -17px 0 -17px;
+    display: none;
+}
+
+#toc h3 {
+    float: right;
+    margin: 5px 5px 0 0;
+    padding: 0;
+    font-size: 12px;
+    color: #777;
+}
+
+#toc h3:hover {
+    color: #333;
+    cursor: pointer;
+}
+
+.expandedtoc {
+    background: #222 url(darkmetal.png);
+    border-bottom: 1px solid #111;
+    outline-bottom: 1px solid #000;
+    padding: 5px;
+}
+
+.expandedtoc h3 {
+    color: #aaa;
+    margin: 0!important;
+}
+
+.expandedtoc h3:hover {
+    color: white!important;
+}
+
+#tod h3:hover {
+    color: white;
+}
+
+#toc a {
+    color: #ddd;
+    text-decoration: none;
+}
+
+#toc a:hover {
+    color: white;
+    text-decoration: underline;
+}
+
+#toc ul {
+    margin: 5px 0 12px 17px;
+    padding: 0 7px 0 7px;
+}
+
+#toc ul ul {
+    margin-bottom: 0;
+}
+
+#toc ul li {
+    margin: 2px 0 0 0;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html b/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html
new file mode 100644
index 0000000..9add6e9
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_templates/genindex.html
@@ -0,0 +1,36 @@
+{% extends "layout.html" %}
+{% set title = 'Index' %}
+{% block body %}
+
+  <h1 id="index">Index</h1>
+
+  {% for key, dummy in genindexentries -%}
+  <a href="#{{ key }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %}
+  {%- endfor %}
+  <hr>
+
+  {% for key, entries in genindexentries %}
+    <h2 id="{{ key }}">{{ key }}</h2>
+    <table class="indextable"><tr>
+    {%- for column in entries|slice(2) if column %}
+      <td><dl>
+      {%- for entryname, (links, subitems) in column %}
+        <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
+          {% for link in links[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor %}
+          {%- else %}{{ entryname|e }}{% endif %}</dt>
+        {%- if subitems %}
+        <dd><dl>
+          {%- for subentryname, subentrylinks in subitems %}
+          <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
+          {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor -%}
+          </dt>
+          {%- endfor %}
+        </dl></dd>
+        {%- endif -%}
+      {%- endfor %}
+      </dl></td>
+    {%- endfor %}
+    </tr></table>
+  {% endfor %}
+
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/layout.html b/ambari-common/src/main/python/jinja2/docs/_templates/layout.html
new file mode 100644
index 0000000..f682f90
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_templates/layout.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <title>Jinja2 Documentation</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}" type="text/css">
+    <link rel="stylesheet" href="{{ pathto('_static/print.css', 1) }}" type="text/css" media="print">
+    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css">
+    {%- if builder != 'htmlhelp' %}
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:   '{{ pathto("", 1) }}',
+        VERSION:    '{{ release }}'
+      };
+    </script>
+    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/jinja.js', 1) }}"></script>
+    {%- endif %}
+    {%- if use_opensearch and builder != 'htmlhelp' %}
+    <link rel="search" type="application/opensearchdescription+xml"
+          title="Search within {{ docstitle }}"
+          href="{{ pathto('_static/opensearch.xml', 1) }}">
+    {%- endif %}
+    {%- if hasdoc('about') %}
+    <link rel="author" title="About these documents" href="{{ pathto('about') }}">
+    {%- endif %}
+    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}">
+    <link rel="index" title="Global index" href="{{ pathto('genindex') }}">
+    <link rel="search" title="Search" href="{{ pathto('search') }}">
+    {%- if hasdoc('copyright') %}
+    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}">
+    {%- endif %}
+    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}">
+    {%- if parents %}
+    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}">
+    {%- endif %}
+    {%- if next %}
+    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}">
+    {%- endif %}
+    {%- if prev %}
+    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}">
+    {%- endif %}
+    {% block extrahead %}{% endblock %}
+  </head>
+  <body>
+    <div id="content">
+      <div class="header">
+        <h1 class="heading"><a href="{{ pathto('index') }}"
+          title="back to the documentation overview"><span>Jinja</span></a></h1>
+      </div>
+      <div class="relnav">
+        {%- if prev %}
+        <a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
+        {%- endif %}
+        <a href="{{ pathto(current_page_name) if current_page_name else '#' }}">{{ title }}</a>
+        {%- if next %}
+        | <a href="{{ next.link|e }}">{{ next.title }} &raquo;</a>
+        {%- endif %}
+      </div>
+      <div id="contentwrapper">
+        {%- if display_toc %}
+        <div id="toc">
+          <h3>Table Of Contents</h3>
+          {{ toc }}
+        </div>
+        {%- endif %}
+        {% block body %}{% endblock %}
+      </div>
+    </div>
+    <div class="footer">
+      © Copyright 2010 by the <a href="http://pocoo.org/">Pocoo Team</a>,
+      documentation generated by <a href="http://sphinx.pocoo.org/">Sphinx</a>
+    </div>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml b/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml
new file mode 100644
index 0000000..9f2fa42
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_templates/opensearch.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>{{ project }}</ShortName>
+  <Description>Search {{ docstitle }}</Description>
+  <InputEncoding>utf-8</InputEncoding>
+  <Url type="text/html" method="get"
+       template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&amp;check_keywords=yes&amp;area=default"/>
+  <LongName>{{ docstitle }}</LongName>
+</OpenSearchDescription>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_templates/page.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/page.html b/ambari-common/src/main/python/jinja2/docs/_templates/page.html
new file mode 100644
index 0000000..ee6cad3
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_templates/page.html
@@ -0,0 +1,4 @@
+{% extends 'layout.html' %}
+{% block body %}
+  {{ body }}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/_templates/search.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/_templates/search.html b/ambari-common/src/main/python/jinja2/docs/_templates/search.html
new file mode 100644
index 0000000..0c942b7
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/_templates/search.html
@@ -0,0 +1,35 @@
+{% extends "layout.html" %}
+{% set title = 'Search' %}
+{% block extrahead %}
+    <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
+{% endblock %}
+{% block body %}
+  <h1 id="search-documentation">Search</h1>
+  <p>
+    From here you can search these documents. Enter your search
+    words into the box below and click "search". Note that the search
+    function will automatically search for all of the words. Pages
+    containing less words won't appear in the result list.
+  </p>
+  <form action="" method="get"><p>
+    <input type="text" name="q" value="">
+    <input type="submit" value="search">
+  </p></form>
+  {% if search_performed %}
+    <h2>Search Results</h2>
+    {% if not search_results %}
+      <p>Your search did not match any results.</p>
+    {% endif %}
+  {% endif %}
+  <div id="search-results">
+  {% if search_results %}
+    <ul>
+    {% for href, caption, context in search_results %}
+      <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
+        <div class="context">{{ context|e }}</div>
+      </li>
+    {% endfor %}
+    </ul>
+  {% endif %}
+  </div>
+{% endblock %}


[51/59] [abbrv] git commit: AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/658360a5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/658360a5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/658360a5

Branch: refs/heads/branch-alerts-dev
Commit: 658360a5a334b79f8012fd6e07b5017a3bf2b1e7
Parents: a537b8e
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Thu Sep 4 16:06:32 2014 +0300
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Thu Sep 4 16:06:32 2014 +0300

----------------------------------------------------------------------
 ambari-agent/pom.xml                            |   12 +-
 .../resource_management/TestContentSources.py   |    2 +-
 .../src/main/python/ambari_jinja2/AUTHORS       |   31 +
 .../src/main/python/ambari_jinja2/CHANGES       |  235 +++
 .../src/main/python/ambari_jinja2/LICENSE       |   31 +
 .../src/main/python/ambari_jinja2/MANIFEST.in   |   12 +
 .../src/main/python/ambari_jinja2/Makefile      |    4 +
 .../ambari_jinja2/ambari_jinja2/__init__.py     |   73 +
 .../ambari_jinja2/ambari_jinja2/_debugsupport.c |   78 +
 .../ambari_jinja2/_markupsafe/__init__.py       |  225 +++
 .../ambari_jinja2/_markupsafe/_bundle.py        |   49 +
 .../ambari_jinja2/_markupsafe/_constants.py     |  267 +++
 .../ambari_jinja2/_markupsafe/_native.py        |   45 +
 .../ambari_jinja2/_markupsafe/tests.py          |   80 +
 .../ambari_jinja2/ambari_jinja2/_stringdefs.py  |  130 ++
 .../ambari_jinja2/ambari_jinja2/bccache.py      |  280 +++
 .../ambari_jinja2/ambari_jinja2/compiler.py     | 1640 ++++++++++++++++++
 .../ambari_jinja2/ambari_jinja2/constants.py    |   32 +
 .../python/ambari_jinja2/ambari_jinja2/debug.py |  308 ++++
 .../ambari_jinja2/ambari_jinja2/defaults.py     |   40 +
 .../ambari_jinja2/ambari_jinja2/environment.py  | 1118 ++++++++++++
 .../ambari_jinja2/ambari_jinja2/exceptions.py   |  143 ++
 .../python/ambari_jinja2/ambari_jinja2/ext.py   |  610 +++++++
 .../ambari_jinja2/ambari_jinja2/filters.py      |  719 ++++++++
 .../python/ambari_jinja2/ambari_jinja2/lexer.py |  681 ++++++++
 .../ambari_jinja2/ambari_jinja2/loaders.py      |  449 +++++
 .../python/ambari_jinja2/ambari_jinja2/meta.py  |  102 ++
 .../python/ambari_jinja2/ambari_jinja2/nodes.py |  901 ++++++++++
 .../ambari_jinja2/ambari_jinja2/optimizer.py    |   68 +
 .../ambari_jinja2/ambari_jinja2/parser.py       |  896 ++++++++++
 .../ambari_jinja2/ambari_jinja2/runtime.py      |  544 ++++++
 .../ambari_jinja2/ambari_jinja2/sandbox.py      |  271 +++
 .../python/ambari_jinja2/ambari_jinja2/tests.py |  146 ++
 .../ambari_jinja2/testsuite/__init__.py         |   95 +
 .../ambari_jinja2/testsuite/api.py              |  240 +++
 .../ambari_jinja2/testsuite/core_tags.py        |  286 +++
 .../ambari_jinja2/testsuite/debug.py            |   60 +
 .../ambari_jinja2/testsuite/doctests.py         |   29 +
 .../ambari_jinja2/testsuite/ext.py              |  455 +++++
 .../ambari_jinja2/testsuite/filters.py          |  291 ++++
 .../ambari_jinja2/testsuite/imports.py          |  144 ++
 .../ambari_jinja2/testsuite/inheritance.py      |  208 +++
 .../ambari_jinja2/testsuite/lexnparse.py        |  390 +++++
 .../ambari_jinja2/testsuite/loader.py           |  191 ++
 .../ambari_jinja2/testsuite/regression.py       |  258 +++
 .../testsuite/res/templates/broken.html         |    3 +
 .../testsuite/res/templates/foo/test.html       |    1 +
 .../testsuite/res/templates/syntaxerror.html    |    4 +
 .../testsuite/res/templates/test.html           |    1 +
 .../ambari_jinja2/testsuite/security.py         |  134 ++
 .../ambari_jinja2/testsuite/tests.py            |   87 +
 .../ambari_jinja2/testsuite/utils.py            |   85 +
 .../python/ambari_jinja2/ambari_jinja2/utils.py |  601 +++++++
 .../ambari_jinja2/ambari_jinja2/visitor.py      |   87 +
 .../python/ambari_jinja2/artwork/jinjalogo.svg  |  132 ++
 .../custom_fixers/fix_alt_unicode.py            |   13 +
 .../custom_fixers/fix_broken_reraising.py       |   21 +
 .../ambari_jinja2/custom_fixers/fix_xrange2.py  |   11 +
 .../src/main/python/ambari_jinja2/docs/Makefile |   75 +
 .../python/ambari_jinja2/docs/_static/jinja.js  |   26 +
 .../python/ambari_jinja2/docs/_static/print.css |    5 +
 .../python/ambari_jinja2/docs/_static/style.css |  390 +++++
 .../ambari_jinja2/docs/_templates/genindex.html |   36 +
 .../ambari_jinja2/docs/_templates/layout.html   |   77 +
 .../docs/_templates/opensearch.xml              |    9 +
 .../ambari_jinja2/docs/_templates/page.html     |    4 +
 .../ambari_jinja2/docs/_templates/search.html   |   35 +
 .../src/main/python/ambari_jinja2/docs/api.rst  |  787 +++++++++
 .../ambari_jinja2/docs/cache_extension.py       |   56 +
 .../python/ambari_jinja2/docs/changelog.rst     |    3 +
 .../src/main/python/ambari_jinja2/docs/conf.py  |  141 ++
 .../python/ambari_jinja2/docs/extensions.rst    |  347 ++++
 .../src/main/python/ambari_jinja2/docs/faq.rst  |  191 ++
 .../main/python/ambari_jinja2/docs/index.rst    |   27 +
 .../python/ambari_jinja2/docs/integration.rst   |   88 +
 .../main/python/ambari_jinja2/docs/intro.rst    |  168 ++
 .../main/python/ambari_jinja2/docs/jinjaext.py  |  192 ++
 .../main/python/ambari_jinja2/docs/sandbox.rst  |   46 +
 .../python/ambari_jinja2/docs/switching.rst     |  242 +++
 .../python/ambari_jinja2/docs/templates.rst     | 1365 +++++++++++++++
 .../main/python/ambari_jinja2/docs/tricks.rst   |  100 ++
 .../ambari_jinja2/examples/basic/cycle.py       |   13 +
 .../ambari_jinja2/examples/basic/debugger.py    |    7 +
 .../ambari_jinja2/examples/basic/inheritance.py |   12 +
 .../examples/basic/templates/broken.html        |    6 +
 .../examples/basic/templates/subbroken.html     |    3 +
 .../python/ambari_jinja2/examples/basic/test.py |   27 +
 .../basic/test_filter_and_linestatements.py     |   25 +
 .../examples/basic/test_loop_filter.py          |   12 +
 .../ambari_jinja2/examples/basic/translate.py   |    6 +
 .../main/python/ambari_jinja2/examples/bench.py |  433 +++++
 .../python/ambari_jinja2/examples/profile.py    |   52 +
 .../examples/rwbench/django/_form.html          |    1 +
 .../examples/rwbench/django/_input_field.html   |    1 +
 .../examples/rwbench/django/_textarea.html      |    1 +
 .../examples/rwbench/django/index.html          |   29 +
 .../examples/rwbench/django/layout.html         |   29 +
 .../ambari_jinja2/examples/rwbench/djangoext.py |  135 ++
 .../examples/rwbench/genshi/helpers.html        |   12 +
 .../examples/rwbench/genshi/index.html          |   41 +
 .../examples/rwbench/genshi/layout.html         |   30 +
 .../examples/rwbench/jinja/helpers.html         |   12 +
 .../examples/rwbench/jinja/index.html           |   29 +
 .../examples/rwbench/jinja/layout.html          |   29 +
 .../examples/rwbench/mako/helpers.html          |   11 +
 .../examples/rwbench/mako/index.html            |   31 +
 .../examples/rwbench/mako/layout.html           |   30 +
 .../ambari_jinja2/examples/rwbench/rwbench.py   |  112 ++
 .../python/ambari_jinja2/ext/Vim/htmljinja.vim  |   27 +
 .../main/python/ambari_jinja2/ext/Vim/jinja.vim |  113 ++
 .../ext/django2jinja/django2jinja.py            |  768 ++++++++
 .../ambari_jinja2/ext/django2jinja/example.py   |    7 +
 .../ext/django2jinja/templates/index.html       |   58 +
 .../ext/django2jinja/templates/layout.html      |    4 +
 .../ext/django2jinja/templates/subtemplate.html |    1 +
 .../python/ambari_jinja2/ext/djangojinja2.py    |   86 +
 .../python/ambari_jinja2/ext/inlinegettext.py   |   78 +
 .../src/main/python/ambari_jinja2/ext/jinja.el  |  213 +++
 .../main/python/ambari_jinja2/jinja2-debug.py   |   40 +
 .../main/python/ambari_jinja2/scripts/pylintrc  |  301 ++++
 .../src/main/python/ambari_jinja2/setup.cfg     |    6 +
 .../src/main/python/ambari_jinja2/setup.py      |  110 ++
 ambari-common/src/main/python/jinja2/AUTHORS    |   31 -
 ambari-common/src/main/python/jinja2/CHANGES    |  235 ---
 ambari-common/src/main/python/jinja2/LICENSE    |   31 -
 .../src/main/python/jinja2/MANIFEST.in          |   12 -
 ambari-common/src/main/python/jinja2/Makefile   |    4 -
 .../main/python/jinja2/artwork/jinjalogo.svg    |  132 --
 .../python/jinja2/custom_fixers/__init__.py     |    0
 .../jinja2/custom_fixers/fix_alt_unicode.py     |   13 -
 .../custom_fixers/fix_broken_reraising.py       |   21 -
 .../python/jinja2/custom_fixers/fix_xrange2.py  |   11 -
 .../src/main/python/jinja2/docs/Makefile        |   75 -
 .../src/main/python/jinja2/docs/_build/.ignore  |    0
 .../src/main/python/jinja2/docs/_static/.ignore |    0
 .../main/python/jinja2/docs/_static/jinja.js    |   26 -
 .../main/python/jinja2/docs/_static/print.css   |    5 -
 .../main/python/jinja2/docs/_static/style.css   |  390 -----
 .../main/python/jinja2/docs/_templates/.ignore  |    0
 .../python/jinja2/docs/_templates/genindex.html |   36 -
 .../python/jinja2/docs/_templates/layout.html   |   77 -
 .../jinja2/docs/_templates/opensearch.xml       |    9 -
 .../python/jinja2/docs/_templates/page.html     |    4 -
 .../python/jinja2/docs/_templates/search.html   |   35 -
 .../src/main/python/jinja2/docs/api.rst         |  787 ---------
 .../main/python/jinja2/docs/cache_extension.py  |   56 -
 .../src/main/python/jinja2/docs/changelog.rst   |    3 -
 .../src/main/python/jinja2/docs/conf.py         |  141 --
 .../src/main/python/jinja2/docs/extensions.rst  |  347 ----
 .../src/main/python/jinja2/docs/faq.rst         |  191 --
 .../src/main/python/jinja2/docs/index.rst       |   27 -
 .../src/main/python/jinja2/docs/integration.rst |   88 -
 .../src/main/python/jinja2/docs/intro.rst       |  168 --
 .../src/main/python/jinja2/docs/jinjaext.py     |  192 --
 .../src/main/python/jinja2/docs/sandbox.rst     |   46 -
 .../src/main/python/jinja2/docs/switching.rst   |  242 ---
 .../src/main/python/jinja2/docs/templates.rst   | 1365 ---------------
 .../src/main/python/jinja2/docs/tricks.rst      |  100 --
 .../main/python/jinja2/examples/basic/cycle.py  |   13 -
 .../python/jinja2/examples/basic/debugger.py    |    7 -
 .../python/jinja2/examples/basic/inheritance.py |   12 -
 .../jinja2/examples/basic/templates/broken.html |    6 -
 .../examples/basic/templates/subbroken.html     |    3 -
 .../main/python/jinja2/examples/basic/test.py   |   27 -
 .../basic/test_filter_and_linestatements.py     |   25 -
 .../jinja2/examples/basic/test_loop_filter.py   |   12 -
 .../python/jinja2/examples/basic/translate.py   |    6 -
 .../src/main/python/jinja2/examples/bench.py    |  433 -----
 .../src/main/python/jinja2/examples/profile.py  |   52 -
 .../jinja2/examples/rwbench/django/_form.html   |    1 -
 .../examples/rwbench/django/_input_field.html   |    1 -
 .../examples/rwbench/django/_textarea.html      |    1 -
 .../jinja2/examples/rwbench/django/index.html   |   29 -
 .../jinja2/examples/rwbench/django/layout.html  |   29 -
 .../python/jinja2/examples/rwbench/djangoext.py |  135 --
 .../jinja2/examples/rwbench/genshi/helpers.html |   12 -
 .../jinja2/examples/rwbench/genshi/index.html   |   41 -
 .../jinja2/examples/rwbench/genshi/layout.html  |   30 -
 .../jinja2/examples/rwbench/jinja/helpers.html  |   12 -
 .../jinja2/examples/rwbench/jinja/index.html    |   29 -
 .../jinja2/examples/rwbench/jinja/layout.html   |   29 -
 .../jinja2/examples/rwbench/mako/helpers.html   |   11 -
 .../jinja2/examples/rwbench/mako/index.html     |   31 -
 .../jinja2/examples/rwbench/mako/layout.html    |   30 -
 .../python/jinja2/examples/rwbench/rwbench.py   |  112 --
 .../main/python/jinja2/ext/Vim/htmljinja.vim    |   27 -
 .../src/main/python/jinja2/ext/Vim/jinja.vim    |  113 --
 .../jinja2/ext/django2jinja/django2jinja.py     |  768 --------
 .../python/jinja2/ext/django2jinja/example.py   |    7 -
 .../ext/django2jinja/templates/index.html       |   58 -
 .../ext/django2jinja/templates/layout.html      |    4 -
 .../ext/django2jinja/templates/subtemplate.html |    1 -
 .../src/main/python/jinja2/ext/djangojinja2.py  |   86 -
 .../src/main/python/jinja2/ext/inlinegettext.py |   78 -
 .../src/main/python/jinja2/ext/jinja.el         |  213 ---
 .../src/main/python/jinja2/jinja2-debug.py      |   40 -
 .../src/main/python/jinja2/jinja2/__init__.py   |   73 -
 .../main/python/jinja2/jinja2/_debugsupport.c   |   78 -
 .../jinja2/jinja2/_markupsafe/__init__.py       |  225 ---
 .../python/jinja2/jinja2/_markupsafe/_bundle.py |   49 -
 .../jinja2/jinja2/_markupsafe/_constants.py     |  267 ---
 .../python/jinja2/jinja2/_markupsafe/_native.py |   45 -
 .../python/jinja2/jinja2/_markupsafe/tests.py   |   80 -
 .../main/python/jinja2/jinja2/_stringdefs.py    |  130 --
 .../src/main/python/jinja2/jinja2/bccache.py    |  280 ---
 .../src/main/python/jinja2/jinja2/compiler.py   | 1640 ------------------
 .../src/main/python/jinja2/jinja2/constants.py  |   32 -
 .../src/main/python/jinja2/jinja2/debug.py      |  308 ----
 .../src/main/python/jinja2/jinja2/defaults.py   |   40 -
 .../main/python/jinja2/jinja2/environment.py    | 1118 ------------
 .../src/main/python/jinja2/jinja2/exceptions.py |  143 --
 .../src/main/python/jinja2/jinja2/ext.py        |  610 -------
 .../src/main/python/jinja2/jinja2/filters.py    |  719 --------
 .../src/main/python/jinja2/jinja2/lexer.py      |  681 --------
 .../src/main/python/jinja2/jinja2/loaders.py    |  449 -----
 .../src/main/python/jinja2/jinja2/meta.py       |  102 --
 .../src/main/python/jinja2/jinja2/nodes.py      |  901 ----------
 .../src/main/python/jinja2/jinja2/optimizer.py  |   68 -
 .../src/main/python/jinja2/jinja2/parser.py     |  896 ----------
 .../src/main/python/jinja2/jinja2/runtime.py    |  544 ------
 .../src/main/python/jinja2/jinja2/sandbox.py    |  271 ---
 .../src/main/python/jinja2/jinja2/tests.py      |  146 --
 .../python/jinja2/jinja2/testsuite/__init__.py  |   95 -
 .../main/python/jinja2/jinja2/testsuite/api.py  |  240 ---
 .../python/jinja2/jinja2/testsuite/core_tags.py |  286 ---
 .../python/jinja2/jinja2/testsuite/debug.py     |   60 -
 .../python/jinja2/jinja2/testsuite/doctests.py  |   29 -
 .../main/python/jinja2/jinja2/testsuite/ext.py  |  455 -----
 .../python/jinja2/jinja2/testsuite/filters.py   |  291 ----
 .../python/jinja2/jinja2/testsuite/imports.py   |  144 --
 .../jinja2/jinja2/testsuite/inheritance.py      |  208 ---
 .../python/jinja2/jinja2/testsuite/lexnparse.py |  390 -----
 .../python/jinja2/jinja2/testsuite/loader.py    |  191 --
 .../jinja2/jinja2/testsuite/regression.py       |  258 ---
 .../jinja2/jinja2/testsuite/res/__init__.py     |    0
 .../jinja2/testsuite/res/templates/broken.html  |    3 -
 .../testsuite/res/templates/foo/test.html       |    1 -
 .../testsuite/res/templates/syntaxerror.html    |    4 -
 .../jinja2/testsuite/res/templates/test.html    |    1 -
 .../python/jinja2/jinja2/testsuite/security.py  |  134 --
 .../python/jinja2/jinja2/testsuite/tests.py     |   87 -
 .../python/jinja2/jinja2/testsuite/utils.py     |   85 -
 .../src/main/python/jinja2/jinja2/utils.py      |  601 -------
 .../src/main/python/jinja2/jinja2/visitor.py    |   87 -
 .../src/main/python/jinja2/scripts/pylintrc     |  301 ----
 ambari-common/src/main/python/jinja2/setup.cfg  |    6 -
 ambari-common/src/main/python/jinja2/setup.py   |  110 --
 .../python/resource_management/core/source.py   |    2 +-
 ambari-server/pom.xml                           |    2 +-
 ambari-server/src/test/python/unitTests.py      |    2 +-
 pom.xml                                         |    2 +
 251 files changed, 21398 insertions(+), 21396 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-agent/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-agent/pom.xml b/ambari-agent/pom.xml
index a487aa7..f4cec91 100644
--- a/ambari-agent/pom.xml
+++ b/ambari-agent/pom.xml
@@ -40,7 +40,7 @@
     <agent.install.dir>/usr/lib/python2.6/site-packages/ambari_agent</agent.install.dir>
     <ambari_commons.install.dir>/usr/lib/ambari-agent/lib/ambari_commons</ambari_commons.install.dir>
     <resource_management.install.dir>/usr/lib/ambari-agent/lib/resource_management</resource_management.install.dir>
-    <jinja.install.dir>/usr/lib/python2.6/site-packages/jinja2</jinja.install.dir>
+    <jinja.install.dir>/usr/lib/python2.6/site-packages/ambari_jinja2</jinja.install.dir>
     <lib.dir>/usr/lib/ambari-agent/lib</lib.dir>
     <python.ver>python &gt;= 2.6</python.ver>
     <deb.python.ver>python (&gt;= 2.6)</deb.python.ver>
@@ -115,7 +115,7 @@
                 <argument>unitTests.py</argument>
               </arguments>
               <environmentVariables>
-                <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python/jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/main/python/resource_management:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/../ambari-common/src/main/python:${project.basedir}/src/main/python/ambari_agent:${project.basedir}/src/test/python/ambari_agent:${project.basedir}/src/test/python/resource_management:${project.basedir}/src/main/python:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/package/files:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HDFS/package/files:$PYTHONPATH</PYTHONPATH>
+                <PYTHONPATH>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2:${project.basedir}/../ambari-common/src/main/python/ambari_commons:${project.basedir}/../ambari-common/src/main/python/resource_management:${project.basedir}/../ambari-common/src/test/python:${project.basedir}/../ambari-common/src/main/python:${project.basedir}/src/main/python/ambari_agent:${project.basedir}/src/test/python/ambari_agent:${project.basedir}/src/test/python/resource_management:${project.basedir}/src/main/python:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/package/files:${project.basedir}/../ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HDFS/package/files:$PYTHONPATH</PYTHONPATH>
               </environmentVariables>
               <skip>${skipTests}</skip>
             </configuration>
@@ -255,9 +255,9 @@
               <groupname>root</groupname>
               <sources>
                 <source>
-                  <location>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2</location>
+                  <location>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2</location>
                   <excludes>
-                    <exclude>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2/testsuite</exclude>
+                    <exclude>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite</exclude>
                   </excludes>
                 </source>
               </sources>
@@ -413,8 +413,8 @@
               </mapper>
             </data>
             <data>
-              <src>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2</src>
-              <excludes>${project.basedir}/../ambari-common/src/main/python/jinja2/jinja2/testsuite</excludes>
+              <src>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2</src>
+              <excludes>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite</excludes>
               <type>directory</type>
               <mapper>
                 <type>perm</type>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-agent/src/test/python/resource_management/TestContentSources.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestContentSources.py b/ambari-agent/src/test/python/resource_management/TestContentSources.py
index 2527f30..1c5e8a8 100644
--- a/ambari-agent/src/test/python/resource_management/TestContentSources.py
+++ b/ambari-agent/src/test/python/resource_management/TestContentSources.py
@@ -27,7 +27,7 @@ from resource_management.core.source import DownloadSource
 from resource_management.core.source import Template
 from resource_management.core.source import InlineTemplate
 
-from jinja2 import UndefinedError, TemplateNotFound
+from ambari_jinja2 import UndefinedError, TemplateNotFound
 import urllib2
 import os
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/AUTHORS
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/AUTHORS b/ambari-common/src/main/python/ambari_jinja2/AUTHORS
new file mode 100644
index 0000000..c6cd9ba
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/AUTHORS
@@ -0,0 +1,31 @@
+Jinja is written and maintained by the Jinja Team and various
+contributors:
+
+Lead Developer:
+
+- Armin Ronacher <ar...@active-4.com>
+
+Developers:
+
+- Christoph Hack
+- Georg Brandl
+
+Contributors:
+
+- Bryan McLemore
+- Mickaël Guérin <ka...@crocobox.org>
+- Cameron Knight
+- Lawrence Journal-World.
+- David Cramer
+
+Patches and suggestions:
+
+- Ronny Pfannschmidt
+- Axel Böhm
+- Alexey Melchakov
+- Bryan McLemore
+- Clovis Fabricio (nosklo)
+- Cameron Knight
+- Peter van Dijk (Habbie)
+- Stefan Ebner
+- Rene Leonhardt

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/CHANGES
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/CHANGES b/ambari-common/src/main/python/ambari_jinja2/CHANGES
new file mode 100644
index 0000000..25b8aa4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/CHANGES
@@ -0,0 +1,235 @@
+Jinja2 Changelog
+================
+
+Version 2.5.5
+-------------
+(re-release of 2.5.4 with built documentation removed for filesize.
+ Released on October 18th 2010)
+
+- built documentation is no longer part of release.
+
+Version 2.5.4
+-------------
+(bugfix release, released on October 17th 2010)
+
+- Fixed extensions not loading properly with overlays.
+- Work around a bug in cpython for the debugger that causes segfaults
+  on 64bit big-endian architectures.
+
+Version 2.5.3
+-------------
+(bugfix release, released on October 17th 2010)
+
+- fixed an operator precedence error introduced in 2.5.2.  Statements
+  like "-foo.bar" had their implicit parentheses applied around the
+  first part of the expression ("(-foo).bar") instead of the more
+  correct "-(foo.bar)".
+
+Version 2.5.2
+-------------
+(bugfix release, released on August 18th 2010)
+
+- improved setup.py script to better work with assumptions people
+  might still have from it (``--with-speedups``).
+- fixed a packaging error that excluded the new debug support.
+
+Version 2.5.1
+-------------
+(bugfix release, released on August 17th 2010)
+
+- StopIteration exceptions raised by functions called from templates
+  are now intercepted and converted to undefineds.  This solves a
+  lot of debugging grief.  (StopIteration is used internally to
+  abort template execution)
+- improved performance of macro calls slightly.
+- babel extraction can now properly extract newstyle gettext calls.
+- using the variable `num` in newstyle gettext for something else
+  than the pluralize count will no longer raise a :exc:`KeyError`.
+- removed builtin markup class and switched to markupsafe.  For backwards
+  compatibility the pure Python implementation still exists but is
+  pulled from markupsafe by the Jinja2 developers.  The debug support
+  went into a separate feature called "debugsupport" and is disabled
+  by default because it is only relevant for Python 2.4
+- fixed an issue with unary operators having the wrong precendence.
+
+Version 2.5
+-----------
+(codename Incoherence, relased on May 29th 2010)
+
+- improved the sort filter (should have worked like this for a
+  long time) by adding support for case insensitive searches.
+- fixed a bug for getattribute constant folding.
+- support for newstyle gettext translations which result in a
+  nicer in-template user interface and more consistent
+  catalogs. (:ref:`newstyle-gettext`)
+- it's now possible to register extensions after an environment
+  was created.
+
+Version 2.4.1
+-------------
+(bugfix release, released on April 20th 2010)
+
+- fixed an error reporting bug for undefineds.
+
+Version 2.4
+-----------
+(codename Correlation, released on April 13th 2010)
+
+- the environment template loading functions now transparently
+  pass through a template object if it was passed to it.  This
+  makes it possible to import or extend from a template object
+  that was passed to the template.
+- added a :class:`ModuleLoader` that can load templates from
+  precompiled sources.  The environment now features a method
+  to compile the templates from a configured loader into a zip
+  file or folder.
+- the _speedups C extension now supports Python 3.
+- added support for autoescaping toggling sections and support
+  for evaluation contexts (:ref:`eval-context`).
+- extensions have a priority now.
+
+Version 2.3.1
+-------------
+(bugfix release, released on February 19th 2010)
+
+- fixed an error reporting bug on all python versions
+- fixed an error reporting bug on Python 2.4
+
+Version 2.3
+-----------
+(3000 Pythons, released on February 10th 2010)
+
+- fixes issue with code generator that causes unbound variables
+  to be generated if set was used in if-blocks and other small
+  identifier problems.
+- include tags are now able to select between multiple templates
+  and take the first that exists, if a list of templates is
+  given.
+- fixed a problem with having call blocks in outer scopes that
+  have an argument that is also used as local variable in an
+  inner frame (#360).
+- greatly improved error message reporting (#339)
+- implicit tuple expressions can no longer be totally empty.
+  This change makes ``{% if %}...{% endif %}`` a syntax error
+  now. (#364)
+- added support for translator comments if extracted via babel.
+- added with-statement extension.
+- experimental Python 3 support.
+
+Version 2.2.1
+-------------
+(bugfix release, released on September 14th 2009)
+
+- fixes some smaller problems for Jinja2 on Jython.
+
+Version 2.2
+-----------
+(codename Kong, released on September 13th 2009)
+
+- Include statements can now be marked with ``ignore missing`` to skip
+  non existing templates.
+- Priority of `not` raised.  It's now possible to write `not foo in bar`
+  as an alias to `foo not in bar` like in python.  Previously the grammar
+  required parentheses (`not (foo in bar)`) which was odd.
+- Fixed a bug that caused syntax errors when defining macros or using the
+  `{% call %}` tag inside loops.
+- Fixed a bug in the parser that made ``{{ foo[1, 2] }}`` impossible.
+- Made it possible to refer to names from outer scopes in included templates
+  that were unused in the callers frame (#327)
+- Fixed a bug that caused internal errors if names where used as iteration
+  variable and regular variable *after* the loop if that variable was unused
+  *before* the loop.  (#331)
+- Added support for optional `scoped` modifier to blocks.
+- Added support for line-comments.
+- Added the `meta` module.
+- Renamed (undocumented) attribute "overlay" to "overlayed" on the
+  environment because it was clashing with a method of the same name.
+- speedup extension is now disabled by default.
+
+Version 2.1.1
+-------------
+(Bugfix release)
+
+- Fixed a translation error caused by looping over empty recursive loops.
+
+Version 2.1
+-----------
+(codename Yasuzō, released on November 23rd 2008)
+
+- fixed a bug with nested loops and the special loop variable.  Before the
+  change an inner loop overwrote the loop variable from the outer one after
+  iteration.
+
+- fixed a bug with the i18n extension that caused the explicit pluralization
+  block to look up the wrong variable.
+
+- fixed a limitation in the lexer that made ``{{ foo.0.0 }}`` impossible.
+
+- index based subscribing of variables with a constant value returns an
+  undefined object now instead of raising an index error.  This was a bug
+  caused by eager optimizing.
+
+- the i18n extension looks up `foo.ugettext` now followed by `foo.gettext`
+  if an translations object is installed.  This makes dealing with custom
+  translations classes easier.
+
+- fixed a confusing behavior with conditional extending.  loops were partially
+  executed under some conditions even though they were not part of a visible
+  area.
+
+- added `sort` filter that works like `dictsort` but for arbitrary sequences.
+
+- fixed a bug with empty statements in macros.
+
+- implemented a bytecode cache system.  (:ref:`bytecode-cache`)
+
+- the template context is now weakref-able
+
+- inclusions and imports "with context" forward all variables now, not only
+  the initial context.
+
+- added a cycle helper called `cycler`.
+
+- added a joining helper called `joiner`.
+
+- added a `compile_expression` method to the environment that allows compiling
+  of Jinja expressions into callable Python objects.
+
+- fixed an escaping bug in urlize
+
+Version 2.0
+-----------
+(codename jinjavitus, released on July 17th 2008)
+
+- the subscribing of objects (looking up attributes and items) changed from
+  slightly.  It's now possible to give attributes or items a higher priority
+  by either using dot-notation lookup or the bracket syntax.  This also
+  changed the AST slightly.  `Subscript` is gone and was replaced with
+  :class:`~ambari_jinja2.nodes.Getitem` and :class:`~ambari_jinja2.nodes.Getattr`.
+
+  For more information see :ref:`the implementation details <notes-on-subscriptions>`.
+
+- added support for preprocessing and token stream filtering for extensions.
+  This would allow extensions to allow simplified gettext calls in template
+  data and something similar.
+
+- added :meth:`ambari_jinja2.environment.TemplateStream.dump`.
+
+- added missing support for implicit string literal concatenation.
+  ``{{ "foo" "bar" }}`` is equivalent to ``{{ "foobar" }}``
+
+- `else` is optional for conditional expressions.  If not given it evaluates
+  to `false`.
+
+- improved error reporting for undefined values by providing a position.
+
+- `filesizeformat` filter uses decimal prefixes now per default and can be
+  set to binary mode with the second parameter.
+
+- fixed bug in finalizer
+
+Version 2.0rc1
+--------------
+(no codename, released on June 9th 2008)
+
+- first release of Jinja2

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/LICENSE
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/LICENSE b/ambari-common/src/main/python/ambari_jinja2/LICENSE
new file mode 100644
index 0000000..31bf900
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of the contributors may not be used to endorse or
+      promote products derived from this software without specific
+      prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in b/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in
new file mode 100644
index 0000000..17ef0bd
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/MANIFEST.in
@@ -0,0 +1,12 @@
+include MANIFEST.in Makefile CHANGES LICENSE AUTHORS ambari_jinja2/_debugsupport.c
+recursive-include docs *
+recursive-include custom_fixers *
+recursive-include ext *
+recursive-include artwork *
+recursive-include examples *
+recursive-include ambari_jinja2/testsuite/res *
+recursive-exclude docs/_build *
+recursive-exclude ambari_jinja2 *.pyc
+recursive-exclude docs *.pyc
+recursive-exclude ambari_jinja2 *.pyo
+recursive-exclude docs *.pyo

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/Makefile b/ambari-common/src/main/python/ambari_jinja2/Makefile
new file mode 100644
index 0000000..60ca1d7
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/Makefile
@@ -0,0 +1,4 @@
+test:
+	python setup.py test
+
+.PHONY: test

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py
new file mode 100644
index 0000000..d02aab2
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/__init__.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2
+    ~~~~~~
+
+    Jinja2 is a template engine written in pure Python.  It provides a
+    Django inspired non-XML syntax but supports inline expressions and
+    an optional sandboxed environment.
+
+    Nutshell
+    --------
+
+    Here a small example of a Jinja2 template::
+
+        {% extends 'base.html' %}
+        {% block title %}Memberlist{% endblock %}
+        {% block content %}
+          <ul>
+          {% for user in users %}
+            <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+          {% endfor %}
+          </ul>
+        {% endblock %}
+
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+__docformat__ = 'restructuredtext en'
+try:
+    __version__ = __import__('pkg_resources') \
+        .get_distribution('Jinja2').version
+except:
+    __version__ = 'unknown'
+
+# high level interface
+from ambari_jinja2.environment import Environment, Template
+
+# loaders
+from ambari_jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \
+     DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \
+     ModuleLoader
+
+# bytecode caches
+from ambari_jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
+     MemcachedBytecodeCache
+
+# undefined types
+from ambari_jinja2.runtime import Undefined, DebugUndefined, StrictUndefined
+
+# exceptions
+from ambari_jinja2.exceptions import TemplateError, UndefinedError, \
+     TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \
+     TemplateAssertionError
+
+# decorators and public utilities
+from ambari_jinja2.filters import environmentfilter, contextfilter, \
+     evalcontextfilter
+from ambari_jinja2.utils import Markup, escape, clear_caches, \
+     environmentfunction, evalcontextfunction, contextfunction, \
+     is_undefined
+
+__all__ = [
+    'Environment', 'Template', 'BaseLoader', 'FileSystemLoader',
+    'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader',
+    'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache',
+    'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined',
+    'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound',
+    'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError',
+    'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape',
+    'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined',
+    'evalcontextfilter', 'evalcontextfunction'
+]

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c
new file mode 100644
index 0000000..041c94f
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_debugsupport.c
@@ -0,0 +1,78 @@
+/**
+ * ambari_jinja2._debugsupport
+ * ~~~~~~~~~~~~~~~~~~~~
+ *
+ * C implementation of `tb_set_next`.
+ *
+ * :copyright: (c) 2010 by the Jinja Team.
+ * :license: BSD.
+ */
+
+#include <Python.h>
+
+
+static PyObject*
+tb_set_next(PyObject *self, PyObject *args)
+{
+	PyTracebackObject *tb, *old;
+	PyObject *next;
+
+	if (!PyArg_ParseTuple(args, "O!O:tb_set_next", &PyTraceBack_Type, &tb, &next))
+		return NULL;
+	if (next == Py_None)
+		next = NULL;
+	else if (!PyTraceBack_Check(next)) {
+		PyErr_SetString(PyExc_TypeError,
+				"tb_set_next arg 2 must be traceback or None");
+		return NULL;
+	}
+	else
+		Py_INCREF(next);
+
+	old = tb->tb_next;
+	tb->tb_next = (PyTracebackObject*)next;
+	Py_XDECREF(old);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMethodDef module_methods[] = {
+	{"tb_set_next", (PyCFunction)tb_set_next, METH_VARARGS,
+	 "Set the tb_next member of a traceback object."},
+	{NULL, NULL, 0, NULL}		/* Sentinel */
+};
+
+
+#if PY_MAJOR_VERSION < 3
+
+#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+init_debugsupport(void)
+{
+	Py_InitModule3("ambari_jinja2._debugsupport", module_methods, "");
+}
+
+#else /* Python 3.x module initialization */
+
+static struct PyModuleDef module_definition = {
+        PyModuleDef_HEAD_INIT,
+	"ambari_jinja2._debugsupport",
+	NULL,
+	-1,
+	module_methods,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+PyMODINIT_FUNC
+PyInit__debugsupport(void)
+{
+	return PyModule_Create(&module_definition);
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py
new file mode 100644
index 0000000..74d0fe3
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/__init__.py
@@ -0,0 +1,225 @@
+# -*- coding: utf-8 -*-
+"""
+    markupsafe
+    ~~~~~~~~~~
+
+    Implements a Markup string.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+from itertools import imap
+
+
+__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
+
+
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^;]+);')
+
+
+class Markup(unicode):
+    r"""Marks a string as being safe for inclusion in HTML/XML output without
+    needing to be escaped.  This implements the `__html__` interface a couple
+    of frameworks and web applications use.  :class:`Markup` is a direct
+    subclass of `unicode` and provides all the methods of `unicode` just that
+    it escapes arguments passed and always returns `Markup`.
+
+    The `escape` function returns markup objects so that double escaping can't
+    happen.
+
+    The constructor of the :class:`Markup` class can be used for three
+    different things:  When passed an unicode object it's assumed to be safe,
+    when passed an object with an HTML representation (has an `__html__`
+    method) that representation is used, otherwise the object passed is
+    converted into a unicode string and then assumed to be safe:
+
+    >>> Markup("Hello <em>World</em>!")
+    Markup(u'Hello <em>World</em>!')
+    >>> class Foo(object):
+    ...  def __html__(self):
+    ...   return '<a href="#">foo</a>'
+    ... 
+    >>> Markup(Foo())
+    Markup(u'<a href="#">foo</a>')
+
+    If you want object passed being always treated as unsafe you can use the
+    :meth:`escape` classmethod to create a :class:`Markup` object:
+
+    >>> Markup.escape("Hello <em>World</em>!")
+    Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
+
+    Operations on a markup string are markup aware which means that all
+    arguments are passed through the :func:`escape` function:
+
+    >>> em = Markup("<em>%s</em>")
+    >>> em % "foo & bar"
+    Markup(u'<em>foo &amp; bar</em>')
+    >>> strong = Markup("<strong>%(text)s</strong>")
+    >>> strong % {'text': '<blink>hacker here</blink>'}
+    Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
+    >>> Markup("<em>Hello</em> ") + "<foo>"
+    Markup(u'<em>Hello</em> &lt;foo&gt;')
+    """
+    __slots__ = ()
+
+    def __new__(cls, base=u'', encoding=None, errors='strict'):
+        if hasattr(base, '__html__'):
+            base = base.__html__()
+        if encoding is None:
+            return unicode.__new__(cls, base)
+        return unicode.__new__(cls, base, encoding, errors)
+
+    def __html__(self):
+        return self
+
+    def __add__(self, other):
+        if hasattr(other, '__html__') or isinstance(other, basestring):
+            return self.__class__(unicode(self) + unicode(escape(other)))
+        return NotImplemented
+
+    def __radd__(self, other):
+        if hasattr(other, '__html__') or isinstance(other, basestring):
+            return self.__class__(unicode(escape(other)) + unicode(self))
+        return NotImplemented
+
+    def __mul__(self, num):
+        if isinstance(num, (int, long)):
+            return self.__class__(unicode.__mul__(self, num))
+        return NotImplemented
+    __rmul__ = __mul__
+
+    def __mod__(self, arg):
+        if isinstance(arg, tuple):
+            arg = tuple(imap(_MarkupEscapeHelper, arg))
+        else:
+            arg = _MarkupEscapeHelper(arg)
+        return self.__class__(unicode.__mod__(self, arg))
+
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            unicode.__repr__(self)
+        )
+
+    def join(self, seq):
+        return self.__class__(unicode.join(self, imap(escape, seq)))
+    join.__doc__ = unicode.join.__doc__
+
+    def split(self, *args, **kwargs):
+        return map(self.__class__, unicode.split(self, *args, **kwargs))
+    split.__doc__ = unicode.split.__doc__
+
+    def rsplit(self, *args, **kwargs):
+        return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
+    rsplit.__doc__ = unicode.rsplit.__doc__
+
+    def splitlines(self, *args, **kwargs):
+        return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
+    splitlines.__doc__ = unicode.splitlines.__doc__
+
+    def unescape(self):
+        r"""Unescape markup again into an unicode string.  This also resolves
+        known HTML4 and XHTML entities:
+
+        >>> Markup("Main &raquo; <em>About</em>").unescape()
+        u'Main \xbb <em>About</em>'
+        """
+        from ambari_jinja2._markupsafe._constants import HTML_ENTITIES
+        def handle_match(m):
+            name = m.group(1)
+            if name in HTML_ENTITIES:
+                return unichr(HTML_ENTITIES[name])
+            try:
+                if name[:2] in ('#x', '#X'):
+                    return unichr(int(name[2:], 16))
+                elif name.startswith('#'):
+                    return unichr(int(name[1:]))
+            except ValueError:
+                pass
+            return u''
+        return _entity_re.sub(handle_match, unicode(self))
+
+    def striptags(self):
+        r"""Unescape markup into an unicode string and strip all tags.  This
+        also resolves known HTML4 and XHTML entities.  Whitespace is
+        normalized to one:
+
+        >>> Markup("Main &raquo;  <em>About</em>").striptags()
+        u'Main \xbb About'
+        """
+        stripped = u' '.join(_striptags_re.sub('', self).split())
+        return Markup(stripped).unescape()
+
+    @classmethod
+    def escape(cls, s):
+        """Escape the string.  Works like :func:`escape` with the difference
+        that for subclasses of :class:`Markup` this function would return the
+        correct subclass.
+        """
+        rv = escape(s)
+        if rv.__class__ is not cls:
+            return cls(rv)
+        return rv
+
+    def make_wrapper(name):
+        orig = getattr(unicode, name)
+        def func(self, *args, **kwargs):
+            args = _escape_argspec(list(args), enumerate(args))
+            _escape_argspec(kwargs, kwargs.iteritems())
+            return self.__class__(orig(self, *args, **kwargs))
+        func.__name__ = orig.__name__
+        func.__doc__ = orig.__doc__
+        return func
+
+    for method in '__getitem__', 'capitalize', \
+                  'title', 'lower', 'upper', 'replace', 'ljust', \
+                  'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
+                  'translate', 'expandtabs', 'swapcase', 'zfill':
+        locals()[method] = make_wrapper(method)
+
+    # new in python 2.5
+    if hasattr(unicode, 'partition'):
+        partition = make_wrapper('partition'),
+        rpartition = make_wrapper('rpartition')
+
+    # new in python 2.6
+    if hasattr(unicode, 'format'):
+        format = make_wrapper('format')
+
+    # not in python 3
+    if hasattr(unicode, '__getslice__'):
+        __getslice__ = make_wrapper('__getslice__')
+
+    del method, make_wrapper
+
+
+def _escape_argspec(obj, iterable):
+    """Helper for various string-wrapped functions."""
+    for key, value in iterable:
+        if hasattr(value, '__html__') or isinstance(value, basestring):
+            obj[key] = escape(value)
+    return obj
+
+
+class _MarkupEscapeHelper(object):
+    """Helper for Markup.__mod__"""
+
+    def __init__(self, obj):
+        self.obj = obj
+
+    __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
+    __str__ = lambda s: str(escape(s.obj))
+    __unicode__ = lambda s: unicode(escape(s.obj))
+    __repr__ = lambda s: str(escape(repr(s.obj)))
+    __int__ = lambda s: int(s.obj)
+    __float__ = lambda s: float(s.obj)
+
+
+# we have to import it down here as the speedups and native
+# modules imports the markup type which is define above.
+try:
+    from ambari_jinja2._markupsafe._speedups import escape, escape_silent, soft_unicode
+except ImportError:
+    from ambari_jinja2._markupsafe._native import escape, escape_silent, soft_unicode

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py
new file mode 100644
index 0000000..de5d15e
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_bundle.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2._markupsafe._bundle
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    This script pulls in markupsafe from a source folder and
+    bundles it with Jinja2.  It does not pull in the speedups
+    module though.
+
+    :copyright: Copyright 2010 by the Jinja team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+import sys
+import os
+import re
+
+
+def rewrite_imports(lines):
+    for idx, line in enumerate(lines):
+        new_line = re.sub(r'(import|from)\s+markupsafe\b',
+                          r'\1 ambari_jinja2._markupsafe', line)
+        if new_line != line:
+            lines[idx] = new_line
+
+
+def main():
+    if len(sys.argv) != 2:
+        print 'error: only argument is path to markupsafe'
+        sys.exit(1)
+    basedir = os.path.dirname(__file__)
+    markupdir = sys.argv[1]
+    for filename in os.listdir(markupdir):
+        if filename.endswith('.py'):
+            f = open(os.path.join(markupdir, filename))
+            try:
+                lines = list(f)
+            finally:
+                f.close()
+            rewrite_imports(lines)
+            f = open(os.path.join(basedir, filename), 'w')
+            try:
+                for line in lines:
+                    f.write(line)
+            finally:
+                f.close()
+
+
+if __name__ == '__main__':
+    main()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py
new file mode 100644
index 0000000..919bf03
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_constants.py
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+"""
+    markupsafe._constants
+    ~~~~~~~~~~~~~~~~~~~~~
+
+    Highlevel implementation of the Markup string.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+
+
+HTML_ENTITIES = {
+    'AElig': 198,
+    'Aacute': 193,
+    'Acirc': 194,
+    'Agrave': 192,
+    'Alpha': 913,
+    'Aring': 197,
+    'Atilde': 195,
+    'Auml': 196,
+    'Beta': 914,
+    'Ccedil': 199,
+    'Chi': 935,
+    'Dagger': 8225,
+    'Delta': 916,
+    'ETH': 208,
+    'Eacute': 201,
+    'Ecirc': 202,
+    'Egrave': 200,
+    'Epsilon': 917,
+    'Eta': 919,
+    'Euml': 203,
+    'Gamma': 915,
+    'Iacute': 205,
+    'Icirc': 206,
+    'Igrave': 204,
+    'Iota': 921,
+    'Iuml': 207,
+    'Kappa': 922,
+    'Lambda': 923,
+    'Mu': 924,
+    'Ntilde': 209,
+    'Nu': 925,
+    'OElig': 338,
+    'Oacute': 211,
+    'Ocirc': 212,
+    'Ograve': 210,
+    'Omega': 937,
+    'Omicron': 927,
+    'Oslash': 216,
+    'Otilde': 213,
+    'Ouml': 214,
+    'Phi': 934,
+    'Pi': 928,
+    'Prime': 8243,
+    'Psi': 936,
+    'Rho': 929,
+    'Scaron': 352,
+    'Sigma': 931,
+    'THORN': 222,
+    'Tau': 932,
+    'Theta': 920,
+    'Uacute': 218,
+    'Ucirc': 219,
+    'Ugrave': 217,
+    'Upsilon': 933,
+    'Uuml': 220,
+    'Xi': 926,
+    'Yacute': 221,
+    'Yuml': 376,
+    'Zeta': 918,
+    'aacute': 225,
+    'acirc': 226,
+    'acute': 180,
+    'aelig': 230,
+    'agrave': 224,
+    'alefsym': 8501,
+    'alpha': 945,
+    'amp': 38,
+    'and': 8743,
+    'ang': 8736,
+    'apos': 39,
+    'aring': 229,
+    'asymp': 8776,
+    'atilde': 227,
+    'auml': 228,
+    'bdquo': 8222,
+    'beta': 946,
+    'brvbar': 166,
+    'bull': 8226,
+    'cap': 8745,
+    'ccedil': 231,
+    'cedil': 184,
+    'cent': 162,
+    'chi': 967,
+    'circ': 710,
+    'clubs': 9827,
+    'cong': 8773,
+    'copy': 169,
+    'crarr': 8629,
+    'cup': 8746,
+    'curren': 164,
+    'dArr': 8659,
+    'dagger': 8224,
+    'darr': 8595,
+    'deg': 176,
+    'delta': 948,
+    'diams': 9830,
+    'divide': 247,
+    'eacute': 233,
+    'ecirc': 234,
+    'egrave': 232,
+    'empty': 8709,
+    'emsp': 8195,
+    'ensp': 8194,
+    'epsilon': 949,
+    'equiv': 8801,
+    'eta': 951,
+    'eth': 240,
+    'euml': 235,
+    'euro': 8364,
+    'exist': 8707,
+    'fnof': 402,
+    'forall': 8704,
+    'frac12': 189,
+    'frac14': 188,
+    'frac34': 190,
+    'frasl': 8260,
+    'gamma': 947,
+    'ge': 8805,
+    'gt': 62,
+    'hArr': 8660,
+    'harr': 8596,
+    'hearts': 9829,
+    'hellip': 8230,
+    'iacute': 237,
+    'icirc': 238,
+    'iexcl': 161,
+    'igrave': 236,
+    'image': 8465,
+    'infin': 8734,
+    'int': 8747,
+    'iota': 953,
+    'iquest': 191,
+    'isin': 8712,
+    'iuml': 239,
+    'kappa': 954,
+    'lArr': 8656,
+    'lambda': 955,
+    'lang': 9001,
+    'laquo': 171,
+    'larr': 8592,
+    'lceil': 8968,
+    'ldquo': 8220,
+    'le': 8804,
+    'lfloor': 8970,
+    'lowast': 8727,
+    'loz': 9674,
+    'lrm': 8206,
+    'lsaquo': 8249,
+    'lsquo': 8216,
+    'lt': 60,
+    'macr': 175,
+    'mdash': 8212,
+    'micro': 181,
+    'middot': 183,
+    'minus': 8722,
+    'mu': 956,
+    'nabla': 8711,
+    'nbsp': 160,
+    'ndash': 8211,
+    'ne': 8800,
+    'ni': 8715,
+    'not': 172,
+    'notin': 8713,
+    'nsub': 8836,
+    'ntilde': 241,
+    'nu': 957,
+    'oacute': 243,
+    'ocirc': 244,
+    'oelig': 339,
+    'ograve': 242,
+    'oline': 8254,
+    'omega': 969,
+    'omicron': 959,
+    'oplus': 8853,
+    'or': 8744,
+    'ordf': 170,
+    'ordm': 186,
+    'oslash': 248,
+    'otilde': 245,
+    'otimes': 8855,
+    'ouml': 246,
+    'para': 182,
+    'part': 8706,
+    'permil': 8240,
+    'perp': 8869,
+    'phi': 966,
+    'pi': 960,
+    'piv': 982,
+    'plusmn': 177,
+    'pound': 163,
+    'prime': 8242,
+    'prod': 8719,
+    'prop': 8733,
+    'psi': 968,
+    'quot': 34,
+    'rArr': 8658,
+    'radic': 8730,
+    'rang': 9002,
+    'raquo': 187,
+    'rarr': 8594,
+    'rceil': 8969,
+    'rdquo': 8221,
+    'real': 8476,
+    'reg': 174,
+    'rfloor': 8971,
+    'rho': 961,
+    'rlm': 8207,
+    'rsaquo': 8250,
+    'rsquo': 8217,
+    'sbquo': 8218,
+    'scaron': 353,
+    'sdot': 8901,
+    'sect': 167,
+    'shy': 173,
+    'sigma': 963,
+    'sigmaf': 962,
+    'sim': 8764,
+    'spades': 9824,
+    'sub': 8834,
+    'sube': 8838,
+    'sum': 8721,
+    'sup': 8835,
+    'sup1': 185,
+    'sup2': 178,
+    'sup3': 179,
+    'supe': 8839,
+    'szlig': 223,
+    'tau': 964,
+    'there4': 8756,
+    'theta': 952,
+    'thetasym': 977,
+    'thinsp': 8201,
+    'thorn': 254,
+    'tilde': 732,
+    'times': 215,
+    'trade': 8482,
+    'uArr': 8657,
+    'uacute': 250,
+    'uarr': 8593,
+    'ucirc': 251,
+    'ugrave': 249,
+    'uml': 168,
+    'upsih': 978,
+    'upsilon': 965,
+    'uuml': 252,
+    'weierp': 8472,
+    'xi': 958,
+    'yacute': 253,
+    'yen': 165,
+    'yuml': 255,
+    'zeta': 950,
+    'zwj': 8205,
+    'zwnj': 8204
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py
new file mode 100644
index 0000000..97c8d35
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/_native.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+"""
+    markupsafe._native
+    ~~~~~~~~~~~~~~~~~~
+
+    Native Python implementation the C module is not compiled.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+from ambari_jinja2._markupsafe import Markup
+
+
+def escape(s):
+    """Convert the characters &, <, >, ' and " in string s to HTML-safe
+    sequences.  Use this if you need to display text that might contain
+    such characters in HTML.  Marks return value as markup string.
+    """
+    if hasattr(s, '__html__'):
+        return s.__html__()
+    return Markup(unicode(s)
+        .replace('&', '&amp;')
+        .replace('>', '&gt;')
+        .replace('<', '&lt;')
+        .replace("'", '&#39;')
+        .replace('"', '&#34;')
+    )
+
+
+def escape_silent(s):
+    """Like :func:`escape` but converts `None` into an empty
+    markup string.
+    """
+    if s is None:
+        return Markup()
+    return escape(s)
+
+
+def soft_unicode(s):
+    """Make a string unicode if it isn't already.  That way a markup
+    string is not converted back to unicode.
+    """
+    if not isinstance(s, unicode):
+        s = unicode(s)
+    return s

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py
new file mode 100644
index 0000000..8e88bfe
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_markupsafe/tests.py
@@ -0,0 +1,80 @@
+import gc
+import unittest
+from ambari_jinja2._markupsafe import Markup, escape, escape_silent
+
+
+class MarkupTestCase(unittest.TestCase):
+
+    def test_markup_operations(self):
+        # adding two strings should escape the unsafe one
+        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+        safe = Markup('<em>username</em>')
+        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
+
+        # string interpolations are safe to use too
+        assert Markup('<em>%s</em>') % '<bad user>' == \
+               '<em>&lt;bad user&gt;</em>'
+        assert Markup('<em>%(username)s</em>') % {
+            'username': '<bad user>'
+        } == '<em>&lt;bad user&gt;</em>'
+
+        # an escaped object is markup too
+        assert type(Markup('foo') + 'bar') is Markup
+
+        # and it implements __html__ by returning itself
+        x = Markup("foo")
+        assert x.__html__() is x
+
+        # it also knows how to treat __html__ objects
+        class Foo(object):
+            def __html__(self):
+                return '<em>awesome</em>'
+            def __unicode__(self):
+                return 'awesome'
+        assert Markup(Foo()) == '<em>awesome</em>'
+        assert Markup('<strong>%s</strong>') % Foo() == \
+               '<strong><em>awesome</em></strong>'
+
+        # escaping and unescaping
+        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+        assert Markup("&lt;test&gt;").unescape() == "<test>"
+
+    def test_all_set(self):
+        import ambari_jinja2._markupsafe as markup
+        for item in markup.__all__:
+            getattr(markup, item)
+
+    def test_escape_silent(self):
+        assert escape_silent(None) == Markup()
+        assert escape(None) == Markup(None)
+        assert escape_silent('<foo>') == Markup(u'&lt;foo&gt;')
+
+
+class MarkupLeakTestCase(unittest.TestCase):
+
+    def test_markup_leaks(self):
+        counts = set()
+        for count in xrange(20):
+            for item in xrange(1000):
+                escape("foo")
+                escape("<foo>")
+                escape(u"foo")
+                escape(u"<foo>")
+            counts.add(len(gc.get_objects()))
+        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(MarkupTestCase))
+
+    # this test only tests the c extension
+    if not hasattr(escape, 'func_code'):
+        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
+
+    return suite
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='suite')


[20/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py
deleted file mode 100644
index e728209..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py
+++ /dev/null
@@ -1,280 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.bccache
-    ~~~~~~~~~~~~~~
-
-    This module implements the bytecode cache system Jinja is optionally
-    using.  This is useful if you have very complex template situations and
-    the compiliation of all those templates slow down your application too
-    much.
-
-    Situations where this is useful are often forking web applications that
-    are initialized on the first request.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-from os import path, listdir
-import marshal
-import tempfile
-import cPickle as pickle
-import fnmatch
-from cStringIO import StringIO
-try:
-    from hashlib import sha1
-except ImportError:
-    from sha import new as sha1
-from ambari_jinja2.utils import open_if_exists
-
-
-bc_version = 1
-bc_magic = 'j2'.encode('ascii') + pickle.dumps(bc_version, 2)
-
-
-class Bucket(object):
-    """Buckets are used to store the bytecode for one template.  It's created
-    and initialized by the bytecode cache and passed to the loading functions.
-
-    The buckets get an internal checksum from the cache assigned and use this
-    to automatically reject outdated cache material.  Individual bytecode
-    cache subclasses don't have to care about cache invalidation.
-    """
-
-    def __init__(self, environment, key, checksum):
-        self.environment = environment
-        self.key = key
-        self.checksum = checksum
-        self.reset()
-
-    def reset(self):
-        """Resets the bucket (unloads the bytecode)."""
-        self.code = None
-
-    def load_bytecode(self, f):
-        """Loads bytecode from a file or file like object."""
-        # make sure the magic header is correct
-        magic = f.read(len(bc_magic))
-        if magic != bc_magic:
-            self.reset()
-            return
-        # the source code of the file changed, we need to reload
-        checksum = pickle.load(f)
-        if self.checksum != checksum:
-            self.reset()
-            return
-        # now load the code.  Because marshal is not able to load
-        # from arbitrary streams we have to work around that
-        if isinstance(f, file):
-            self.code = marshal.load(f)
-        else:
-            self.code = marshal.loads(f.read())
-
-    def write_bytecode(self, f):
-        """Dump the bytecode into the file or file like object passed."""
-        if self.code is None:
-            raise TypeError('can\'t write empty bucket')
-        f.write(bc_magic)
-        pickle.dump(self.checksum, f, 2)
-        if isinstance(f, file):
-            marshal.dump(self.code, f)
-        else:
-            f.write(marshal.dumps(self.code))
-
-    def bytecode_from_string(self, string):
-        """Load bytecode from a string."""
-        self.load_bytecode(StringIO(string))
-
-    def bytecode_to_string(self):
-        """Return the bytecode as string."""
-        out = StringIO()
-        self.write_bytecode(out)
-        return out.getvalue()
-
-
-class BytecodeCache(object):
-    """To implement your own bytecode cache you have to subclass this class
-    and override :meth:`load_bytecode` and :meth:`dump_bytecode`.  Both of
-    these methods are passed a :class:`~ambari_jinja2.bccache.Bucket`.
-
-    A very basic bytecode cache that saves the bytecode on the file system::
-
-        from os import path
-
-        class MyCache(BytecodeCache):
-
-            def __init__(self, directory):
-                self.directory = directory
-
-            def load_bytecode(self, bucket):
-                filename = path.join(self.directory, bucket.key)
-                if path.exists(filename):
-                    with open(filename, 'rb') as f:
-                        bucket.load_bytecode(f)
-
-            def dump_bytecode(self, bucket):
-                filename = path.join(self.directory, bucket.key)
-                with open(filename, 'wb') as f:
-                    bucket.write_bytecode(f)
-
-    A more advanced version of a filesystem based bytecode cache is part of
-    Jinja2.
-    """
-
-    def load_bytecode(self, bucket):
-        """Subclasses have to override this method to load bytecode into a
-        bucket.  If they are not able to find code in the cache for the
-        bucket, it must not do anything.
-        """
-        raise NotImplementedError()
-
-    def dump_bytecode(self, bucket):
-        """Subclasses have to override this method to write the bytecode
-        from a bucket back to the cache.  If it unable to do so it must not
-        fail silently but raise an exception.
-        """
-        raise NotImplementedError()
-
-    def clear(self):
-        """Clears the cache.  This method is not used by Jinja2 but should be
-        implemented to allow applications to clear the bytecode cache used
-        by a particular environment.
-        """
-
-    def get_cache_key(self, name, filename=None):
-        """Returns the unique hash key for this template name."""
-        hash = sha1(name.encode('utf-8'))
-        if filename is not None:
-            if isinstance(filename, unicode):
-                filename = filename.encode('utf-8')
-            hash.update('|' + filename)
-        return hash.hexdigest()
-
-    def get_source_checksum(self, source):
-        """Returns a checksum for the source."""
-        return sha1(source.encode('utf-8')).hexdigest()
-
-    def get_bucket(self, environment, name, filename, source):
-        """Return a cache bucket for the given template.  All arguments are
-        mandatory but filename may be `None`.
-        """
-        key = self.get_cache_key(name, filename)
-        checksum = self.get_source_checksum(source)
-        bucket = Bucket(environment, key, checksum)
-        self.load_bytecode(bucket)
-        return bucket
-
-    def set_bucket(self, bucket):
-        """Put the bucket into the cache."""
-        self.dump_bytecode(bucket)
-
-
-class FileSystemBytecodeCache(BytecodeCache):
-    """A bytecode cache that stores bytecode on the filesystem.  It accepts
-    two arguments: The directory where the cache items are stored and a
-    pattern string that is used to build the filename.
-
-    If no directory is specified the system temporary items folder is used.
-
-    The pattern can be used to have multiple separate caches operate on the
-    same directory.  The default pattern is ``'__ambari_jinja2_%s.cache'``.  ``%s``
-    is replaced with the cache key.
-
-    >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
-
-    This bytecode cache supports clearing of the cache using the clear method.
-    """
-
-    def __init__(self, directory=None, pattern='__ambari_jinja2_%s.cache'):
-        if directory is None:
-            directory = tempfile.gettempdir()
-        self.directory = directory
-        self.pattern = pattern
-
-    def _get_cache_filename(self, bucket):
-        return path.join(self.directory, self.pattern % bucket.key)
-
-    def load_bytecode(self, bucket):
-        f = open_if_exists(self._get_cache_filename(bucket), 'rb')
-        if f is not None:
-            try:
-                bucket.load_bytecode(f)
-            finally:
-                f.close()
-
-    def dump_bytecode(self, bucket):
-        f = open(self._get_cache_filename(bucket), 'wb')
-        try:
-            bucket.write_bytecode(f)
-        finally:
-            f.close()
-
-    def clear(self):
-        # imported lazily here because google app-engine doesn't support
-        # write access on the file system and the function does not exist
-        # normally.
-        from os import remove
-        files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
-        for filename in files:
-            try:
-                remove(path.join(self.directory, filename))
-            except OSError:
-                pass
-
-
-class MemcachedBytecodeCache(BytecodeCache):
-    """This class implements a bytecode cache that uses a memcache cache for
-    storing the information.  It does not enforce a specific memcache library
-    (tummy's memcache or cmemcache) but will accept any class that provides
-    the minimal interface required.
-
-    Libraries compatible with this class:
-
-    -   `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
-    -   `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
-    -   `cmemcache <http://gijsbert.org/cmemcache/>`_
-
-    (Unfortunately the django cache interface is not compatible because it
-    does not support storing binary data, only unicode.  You can however pass
-    the underlying cache client to the bytecode cache which is available
-    as `django.core.cache.cache._client`.)
-
-    The minimal interface for the client passed to the constructor is this:
-
-    .. class:: MinimalClientInterface
-
-        .. method:: set(key, value[, timeout])
-
-            Stores the bytecode in the cache.  `value` is a string and
-            `timeout` the timeout of the key.  If timeout is not provided
-            a default timeout or no timeout should be assumed, if it's
-            provided it's an integer with the number of seconds the cache
-            item should exist.
-
-        .. method:: get(key)
-
-            Returns the value for the cache key.  If the item does not
-            exist in the cache the return value must be `None`.
-
-    The other arguments to the constructor are the prefix for all keys that
-    is added before the actual cache key and the timeout for the bytecode in
-    the cache system.  We recommend a high (or no) timeout.
-
-    This bytecode cache does not support clearing of used items in the cache.
-    The clear method is a no-operation function.
-    """
-
-    def __init__(self, client, prefix='ambari_jinja2/bytecode/', timeout=None):
-        self.client = client
-        self.prefix = prefix
-        self.timeout = timeout
-
-    def load_bytecode(self, bucket):
-        code = self.client.get(self.prefix + bucket.key)
-        if code is not None:
-            bucket.bytecode_from_string(code)
-
-    def dump_bytecode(self, bucket):
-        args = (self.prefix + bucket.key, bucket.bytecode_to_string())
-        if self.timeout is not None:
-            args += (self.timeout,)
-        self.client.set(*args)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py
deleted file mode 100644
index f7a52f4..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py
+++ /dev/null
@@ -1,1640 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.compiler
-    ~~~~~~~~~~~~~~~
-
-    Compiles nodes into python code.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from cStringIO import StringIO
-from itertools import chain
-from copy import deepcopy
-from ambari_jinja2 import nodes
-from ambari_jinja2.nodes import EvalContext
-from ambari_jinja2.visitor import NodeVisitor, NodeTransformer
-from ambari_jinja2.exceptions import TemplateAssertionError
-from ambari_jinja2.utils import Markup, concat, escape, is_python_keyword, next
-
-
-operators = {
-    'eq':       '==',
-    'ne':       '!=',
-    'gt':       '>',
-    'gteq':     '>=',
-    'lt':       '<',
-    'lteq':     '<=',
-    'in':       'in',
-    'notin':    'not in'
-}
-
-try:
-    exec '(0 if 0 else 0)'
-except SyntaxError:
-    have_condexpr = False
-else:
-    have_condexpr = True
-
-
-# what method to iterate over items do we want to use for dict iteration
-# in generated code?  on 2.x let's go with iteritems, on 3.x with items
-if hasattr(dict, 'iteritems'):
-    dict_item_iter = 'iteritems'
-else:
-    dict_item_iter = 'items'
-
-
-# does if 0: dummy(x) get us x into the scope?
-def unoptimize_before_dead_code():
-    x = 42
-    def f():
-        if 0: dummy(x)
-    return f
-unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
-
-
-def generate(node, environment, name, filename, stream=None,
-             defer_init=False):
-    """Generate the python source for a node tree."""
-    if not isinstance(node, nodes.Template):
-        raise TypeError('Can\'t compile non template nodes')
-    generator = CodeGenerator(environment, name, filename, stream, defer_init)
-    generator.visit(node)
-    if stream is None:
-        return generator.stream.getvalue()
-
-
-def has_safe_repr(value):
-    """Does the node have a safe representation?"""
-    if value is None or value is NotImplemented or value is Ellipsis:
-        return True
-    if isinstance(value, (bool, int, long, float, complex, basestring,
-                          xrange, Markup)):
-        return True
-    if isinstance(value, (tuple, list, set, frozenset)):
-        for item in value:
-            if not has_safe_repr(item):
-                return False
-        return True
-    elif isinstance(value, dict):
-        for key, value in value.iteritems():
-            if not has_safe_repr(key):
-                return False
-            if not has_safe_repr(value):
-                return False
-        return True
-    return False
-
-
-def find_undeclared(nodes, names):
-    """Check if the names passed are accessed undeclared.  The return value
-    is a set of all the undeclared names from the sequence of names found.
-    """
-    visitor = UndeclaredNameVisitor(names)
-    try:
-        for node in nodes:
-            visitor.visit(node)
-    except VisitorExit:
-        pass
-    return visitor.undeclared
-
-
-class Identifiers(object):
-    """Tracks the status of identifiers in frames."""
-
-    def __init__(self):
-        # variables that are known to be declared (probably from outer
-        # frames or because they are special for the frame)
-        self.declared = set()
-
-        # undeclared variables from outer scopes
-        self.outer_undeclared = set()
-
-        # names that are accessed without being explicitly declared by
-        # this one or any of the outer scopes.  Names can appear both in
-        # declared and undeclared.
-        self.undeclared = set()
-
-        # names that are declared locally
-        self.declared_locally = set()
-
-        # names that are declared by parameters
-        self.declared_parameter = set()
-
-    def add_special(self, name):
-        """Register a special name like `loop`."""
-        self.undeclared.discard(name)
-        self.declared.add(name)
-
-    def is_declared(self, name, local_only=False):
-        """Check if a name is declared in this or an outer scope."""
-        if name in self.declared_locally or name in self.declared_parameter:
-            return True
-        if local_only:
-            return False
-        return name in self.declared
-
-    def copy(self):
-        return deepcopy(self)
-
-
-class Frame(object):
-    """Holds compile time information for us."""
-
-    def __init__(self, eval_ctx, parent=None):
-        self.eval_ctx = eval_ctx
-        self.identifiers = Identifiers()
-
-        # a toplevel frame is the root + soft frames such as if conditions.
-        self.toplevel = False
-
-        # the root frame is basically just the outermost frame, so no if
-        # conditions.  This information is used to optimize inheritance
-        # situations.
-        self.rootlevel = False
-
-        # in some dynamic inheritance situations the compiler needs to add
-        # write tests around output statements.
-        self.require_output_check = parent and parent.require_output_check
-
-        # inside some tags we are using a buffer rather than yield statements.
-        # this for example affects {% filter %} or {% macro %}.  If a frame
-        # is buffered this variable points to the name of the list used as
-        # buffer.
-        self.buffer = None
-
-        # the name of the block we're in, otherwise None.
-        self.block = parent and parent.block or None
-
-        # a set of actually assigned names
-        self.assigned_names = set()
-
-        # the parent of this frame
-        self.parent = parent
-
-        if parent is not None:
-            self.identifiers.declared.update(
-                parent.identifiers.declared |
-                parent.identifiers.declared_parameter |
-                parent.assigned_names
-            )
-            self.identifiers.outer_undeclared.update(
-                parent.identifiers.undeclared -
-                self.identifiers.declared
-            )
-            self.buffer = parent.buffer
-
-    def copy(self):
-        """Create a copy of the current one."""
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.identifiers = object.__new__(self.identifiers.__class__)
-        rv.identifiers.__dict__.update(self.identifiers.__dict__)
-        return rv
-
-    def inspect(self, nodes, hard_scope=False):
-        """Walk the node and check for identifiers.  If the scope is hard (eg:
-        enforce on a python level) overrides from outer scopes are tracked
-        differently.
-        """
-        visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
-        for node in nodes:
-            visitor.visit(node)
-
-    def find_shadowed(self, extra=()):
-        """Find all the shadowed names.  extra is an iterable of variables
-        that may be defined with `add_special` which may occour scoped.
-        """
-        i = self.identifiers
-        return (i.declared | i.outer_undeclared) & \
-               (i.declared_locally | i.declared_parameter) | \
-               set(x for x in extra if i.is_declared(x))
-
-    def inner(self):
-        """Return an inner frame."""
-        return Frame(self.eval_ctx, self)
-
-    def soft(self):
-        """Return a soft frame.  A soft frame may not be modified as
-        standalone thing as it shares the resources with the frame it
-        was created of, but it's not a rootlevel frame any longer.
-        """
-        rv = self.copy()
-        rv.rootlevel = False
-        return rv
-
-    __copy__ = copy
-
-
-class VisitorExit(RuntimeError):
-    """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
-
-
-class DependencyFinderVisitor(NodeVisitor):
-    """A visitor that collects filter and test calls."""
-
-    def __init__(self):
-        self.filters = set()
-        self.tests = set()
-
-    def visit_Filter(self, node):
-        self.generic_visit(node)
-        self.filters.add(node.name)
-
-    def visit_Test(self, node):
-        self.generic_visit(node)
-        self.tests.add(node.name)
-
-    def visit_Block(self, node):
-        """Stop visiting at blocks."""
-
-
-class UndeclaredNameVisitor(NodeVisitor):
-    """A visitor that checks if a name is accessed without being
-    declared.  This is different from the frame visitor as it will
-    not stop at closure frames.
-    """
-
-    def __init__(self, names):
-        self.names = set(names)
-        self.undeclared = set()
-
-    def visit_Name(self, node):
-        if node.ctx == 'load' and node.name in self.names:
-            self.undeclared.add(node.name)
-            if self.undeclared == self.names:
-                raise VisitorExit()
-        else:
-            self.names.discard(node.name)
-
-    def visit_Block(self, node):
-        """Stop visiting a blocks."""
-
-
-class FrameIdentifierVisitor(NodeVisitor):
-    """A visitor for `Frame.inspect`."""
-
-    def __init__(self, identifiers, hard_scope):
-        self.identifiers = identifiers
-        self.hard_scope = hard_scope
-
-    def visit_Name(self, node):
-        """All assignments to names go through this function."""
-        if node.ctx == 'store':
-            self.identifiers.declared_locally.add(node.name)
-        elif node.ctx == 'param':
-            self.identifiers.declared_parameter.add(node.name)
-        elif node.ctx == 'load' and not \
-             self.identifiers.is_declared(node.name, self.hard_scope):
-            self.identifiers.undeclared.add(node.name)
-
-    def visit_If(self, node):
-        self.visit(node.test)
-        real_identifiers = self.identifiers
-
-        old_names = real_identifiers.declared_locally | \
-                    real_identifiers.declared_parameter
-
-        def inner_visit(nodes):
-            if not nodes:
-                return set()
-            self.identifiers = real_identifiers.copy()
-            for subnode in nodes:
-                self.visit(subnode)
-            rv = self.identifiers.declared_locally - old_names
-            # we have to remember the undeclared variables of this branch
-            # because we will have to pull them.
-            real_identifiers.undeclared.update(self.identifiers.undeclared)
-            self.identifiers = real_identifiers
-            return rv
-
-        body = inner_visit(node.body)
-        else_ = inner_visit(node.else_ or ())
-
-        # the differences between the two branches are also pulled as
-        # undeclared variables
-        real_identifiers.undeclared.update(body.symmetric_difference(else_) -
-                                           real_identifiers.declared)
-
-        # remember those that are declared.
-        real_identifiers.declared_locally.update(body | else_)
-
-    def visit_Macro(self, node):
-        self.identifiers.declared_locally.add(node.name)
-
-    def visit_Import(self, node):
-        self.generic_visit(node)
-        self.identifiers.declared_locally.add(node.target)
-
-    def visit_FromImport(self, node):
-        self.generic_visit(node)
-        for name in node.names:
-            if isinstance(name, tuple):
-                self.identifiers.declared_locally.add(name[1])
-            else:
-                self.identifiers.declared_locally.add(name)
-
-    def visit_Assign(self, node):
-        """Visit assignments in the correct order."""
-        self.visit(node.node)
-        self.visit(node.target)
-
-    def visit_For(self, node):
-        """Visiting stops at for blocks.  However the block sequence
-        is visited as part of the outer scope.
-        """
-        self.visit(node.iter)
-
-    def visit_CallBlock(self, node):
-        self.visit(node.call)
-
-    def visit_FilterBlock(self, node):
-        self.visit(node.filter)
-
-    def visit_Scope(self, node):
-        """Stop visiting at scopes."""
-
-    def visit_Block(self, node):
-        """Stop visiting at blocks."""
-
-
-class CompilerExit(Exception):
-    """Raised if the compiler encountered a situation where it just
-    doesn't make sense to further process the code.  Any block that
-    raises such an exception is not further processed.
-    """
-
-
-class CodeGenerator(NodeVisitor):
-
-    def __init__(self, environment, name, filename, stream=None,
-                 defer_init=False):
-        if stream is None:
-            stream = StringIO()
-        self.environment = environment
-        self.name = name
-        self.filename = filename
-        self.stream = stream
-        self.created_block_context = False
-        self.defer_init = defer_init
-
-        # aliases for imports
-        self.import_aliases = {}
-
-        # a registry for all blocks.  Because blocks are moved out
-        # into the global python scope they are registered here
-        self.blocks = {}
-
-        # the number of extends statements so far
-        self.extends_so_far = 0
-
-        # some templates have a rootlevel extends.  In this case we
-        # can safely assume that we're a child template and do some
-        # more optimizations.
-        self.has_known_extends = False
-
-        # the current line number
-        self.code_lineno = 1
-
-        # registry of all filters and tests (global, not block local)
-        self.tests = {}
-        self.filters = {}
-
-        # the debug information
-        self.debug_info = []
-        self._write_debug_info = None
-
-        # the number of new lines before the next write()
-        self._new_lines = 0
-
-        # the line number of the last written statement
-        self._last_line = 0
-
-        # true if nothing was written so far.
-        self._first_write = True
-
-        # used by the `temporary_identifier` method to get new
-        # unique, temporary identifier
-        self._last_identifier = 0
-
-        # the current indentation
-        self._indentation = 0
-
-    # -- Various compilation helpers
-
-    def fail(self, msg, lineno):
-        """Fail with a :exc:`TemplateAssertionError`."""
-        raise TemplateAssertionError(msg, lineno, self.name, self.filename)
-
-    def temporary_identifier(self):
-        """Get a new unique identifier."""
-        self._last_identifier += 1
-        return 't_%d' % self._last_identifier
-
-    def buffer(self, frame):
-        """Enable buffering for the frame from that point onwards."""
-        frame.buffer = self.temporary_identifier()
-        self.writeline('%s = []' % frame.buffer)
-
-    def return_buffer_contents(self, frame):
-        """Return the buffer contents of the frame."""
-        if frame.eval_ctx.volatile:
-            self.writeline('if context.eval_ctx.autoescape:')
-            self.indent()
-            self.writeline('return Markup(concat(%s))' % frame.buffer)
-            self.outdent()
-            self.writeline('else:')
-            self.indent()
-            self.writeline('return concat(%s)' % frame.buffer)
-            self.outdent()
-        elif frame.eval_ctx.autoescape:
-            self.writeline('return Markup(concat(%s))' % frame.buffer)
-        else:
-            self.writeline('return concat(%s)' % frame.buffer)
-
-    def indent(self):
-        """Indent by one."""
-        self._indentation += 1
-
-    def outdent(self, step=1):
-        """Outdent by step."""
-        self._indentation -= step
-
-    def start_write(self, frame, node=None):
-        """Yield or write into the frame buffer."""
-        if frame.buffer is None:
-            self.writeline('yield ', node)
-        else:
-            self.writeline('%s.append(' % frame.buffer, node)
-
-    def end_write(self, frame):
-        """End the writing process started by `start_write`."""
-        if frame.buffer is not None:
-            self.write(')')
-
-    def simple_write(self, s, frame, node=None):
-        """Simple shortcut for start_write + write + end_write."""
-        self.start_write(frame, node)
-        self.write(s)
-        self.end_write(frame)
-
-    def blockvisit(self, nodes, frame):
-        """Visit a list of nodes as block in a frame.  If the current frame
-        is no buffer a dummy ``if 0: yield None`` is written automatically
-        unless the force_generator parameter is set to False.
-        """
-        if frame.buffer is None:
-            self.writeline('if 0: yield None')
-        else:
-            self.writeline('pass')
-        try:
-            for node in nodes:
-                self.visit(node, frame)
-        except CompilerExit:
-            pass
-
-    def write(self, x):
-        """Write a string into the output stream."""
-        if self._new_lines:
-            if not self._first_write:
-                self.stream.write('\n' * self._new_lines)
-                self.code_lineno += self._new_lines
-                if self._write_debug_info is not None:
-                    self.debug_info.append((self._write_debug_info,
-                                            self.code_lineno))
-                    self._write_debug_info = None
-            self._first_write = False
-            self.stream.write('    ' * self._indentation)
-            self._new_lines = 0
-        self.stream.write(x)
-
-    def writeline(self, x, node=None, extra=0):
-        """Combination of newline and write."""
-        self.newline(node, extra)
-        self.write(x)
-
-    def newline(self, node=None, extra=0):
-        """Add one or more newlines before the next write."""
-        self._new_lines = max(self._new_lines, 1 + extra)
-        if node is not None and node.lineno != self._last_line:
-            self._write_debug_info = node.lineno
-            self._last_line = node.lineno
-
-    def signature(self, node, frame, extra_kwargs=None):
-        """Writes a function call to the stream for the current node.
-        A leading comma is added automatically.  The extra keyword
-        arguments may not include python keywords otherwise a syntax
-        error could occour.  The extra keyword arguments should be given
-        as python dict.
-        """
-        # if any of the given keyword arguments is a python keyword
-        # we have to make sure that no invalid call is created.
-        kwarg_workaround = False
-        for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
-            if is_python_keyword(kwarg):
-                kwarg_workaround = True
-                break
-
-        for arg in node.args:
-            self.write(', ')
-            self.visit(arg, frame)
-
-        if not kwarg_workaround:
-            for kwarg in node.kwargs:
-                self.write(', ')
-                self.visit(kwarg, frame)
-            if extra_kwargs is not None:
-                for key, value in extra_kwargs.iteritems():
-                    self.write(', %s=%s' % (key, value))
-        if node.dyn_args:
-            self.write(', *')
-            self.visit(node.dyn_args, frame)
-
-        if kwarg_workaround:
-            if node.dyn_kwargs is not None:
-                self.write(', **dict({')
-            else:
-                self.write(', **{')
-            for kwarg in node.kwargs:
-                self.write('%r: ' % kwarg.key)
-                self.visit(kwarg.value, frame)
-                self.write(', ')
-            if extra_kwargs is not None:
-                for key, value in extra_kwargs.iteritems():
-                    self.write('%r: %s, ' % (key, value))
-            if node.dyn_kwargs is not None:
-                self.write('}, **')
-                self.visit(node.dyn_kwargs, frame)
-                self.write(')')
-            else:
-                self.write('}')
-
-        elif node.dyn_kwargs is not None:
-            self.write(', **')
-            self.visit(node.dyn_kwargs, frame)
-
-    def pull_locals(self, frame):
-        """Pull all the references identifiers into the local scope."""
-        for name in frame.identifiers.undeclared:
-            self.writeline('l_%s = context.resolve(%r)' % (name, name))
-
-    def pull_dependencies(self, nodes):
-        """Pull all the dependencies."""
-        visitor = DependencyFinderVisitor()
-        for node in nodes:
-            visitor.visit(node)
-        for dependency in 'filters', 'tests':
-            mapping = getattr(self, dependency)
-            for name in getattr(visitor, dependency):
-                if name not in mapping:
-                    mapping[name] = self.temporary_identifier()
-                self.writeline('%s = environment.%s[%r]' %
-                               (mapping[name], dependency, name))
-
-    def unoptimize_scope(self, frame):
-        """Disable Python optimizations for the frame."""
-        # XXX: this is not that nice but it has no real overhead.  It
-        # mainly works because python finds the locals before dead code
-        # is removed.  If that breaks we have to add a dummy function
-        # that just accepts the arguments and does nothing.
-        if frame.identifiers.declared:
-            self.writeline('%sdummy(%s)' % (
-                unoptimize_before_dead_code and 'if 0: ' or '',
-                ', '.join('l_' + name for name in frame.identifiers.declared)
-            ))
-
-    def push_scope(self, frame, extra_vars=()):
-        """This function returns all the shadowed variables in a dict
-        in the form name: alias and will write the required assignments
-        into the current scope.  No indentation takes place.
-
-        This also predefines locally declared variables from the loop
-        body because under some circumstances it may be the case that
-
-        `extra_vars` is passed to `Frame.find_shadowed`.
-        """
-        aliases = {}
-        for name in frame.find_shadowed(extra_vars):
-            aliases[name] = ident = self.temporary_identifier()
-            self.writeline('%s = l_%s' % (ident, name))
-        to_declare = set()
-        for name in frame.identifiers.declared_locally:
-            if name not in aliases:
-                to_declare.add('l_' + name)
-        if to_declare:
-            self.writeline(' = '.join(to_declare) + ' = missing')
-        return aliases
-
-    def pop_scope(self, aliases, frame):
-        """Restore all aliases and delete unused variables."""
-        for name, alias in aliases.iteritems():
-            self.writeline('l_%s = %s' % (name, alias))
-        to_delete = set()
-        for name in frame.identifiers.declared_locally:
-            if name not in aliases:
-                to_delete.add('l_' + name)
-        if to_delete:
-            # we cannot use the del statement here because enclosed
-            # scopes can trigger a SyntaxError:
-            #   a = 42; b = lambda: a; del a
-            self.writeline(' = '.join(to_delete) + ' = missing')
-
-    def function_scoping(self, node, frame, children=None,
-                         find_special=True):
-        """In Jinja a few statements require the help of anonymous
-        functions.  Those are currently macros and call blocks and in
-        the future also recursive loops.  As there is currently
-        technical limitation that doesn't allow reading and writing a
-        variable in a scope where the initial value is coming from an
-        outer scope, this function tries to fall back with a common
-        error message.  Additionally the frame passed is modified so
-        that the argumetns are collected and callers are looked up.
-
-        This will return the modified frame.
-        """
-        # we have to iterate twice over it, make sure that works
-        if children is None:
-            children = node.iter_child_nodes()
-        children = list(children)
-        func_frame = frame.inner()
-        func_frame.inspect(children, hard_scope=True)
-
-        # variables that are undeclared (accessed before declaration) and
-        # declared locally *and* part of an outside scope raise a template
-        # assertion error. Reason: we can't generate reasonable code from
-        # it without aliasing all the variables.
-        # this could be fixed in Python 3 where we have the nonlocal
-        # keyword or if we switch to bytecode generation
-        overriden_closure_vars = (
-            func_frame.identifiers.undeclared &
-            func_frame.identifiers.declared &
-            (func_frame.identifiers.declared_locally |
-             func_frame.identifiers.declared_parameter)
-        )
-        if overriden_closure_vars:
-            self.fail('It\'s not possible to set and access variables '
-                      'derived from an outer scope! (affects: %s)' %
-                      ', '.join(sorted(overriden_closure_vars)), node.lineno)
-
-        # remove variables from a closure from the frame's undeclared
-        # identifiers.
-        func_frame.identifiers.undeclared -= (
-            func_frame.identifiers.undeclared &
-            func_frame.identifiers.declared
-        )
-
-        # no special variables for this scope, abort early
-        if not find_special:
-            return func_frame
-
-        func_frame.accesses_kwargs = False
-        func_frame.accesses_varargs = False
-        func_frame.accesses_caller = False
-        func_frame.arguments = args = ['l_' + x.name for x in node.args]
-
-        undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
-
-        if 'caller' in undeclared:
-            func_frame.accesses_caller = True
-            func_frame.identifiers.add_special('caller')
-            args.append('l_caller')
-        if 'kwargs' in undeclared:
-            func_frame.accesses_kwargs = True
-            func_frame.identifiers.add_special('kwargs')
-            args.append('l_kwargs')
-        if 'varargs' in undeclared:
-            func_frame.accesses_varargs = True
-            func_frame.identifiers.add_special('varargs')
-            args.append('l_varargs')
-        return func_frame
-
-    def macro_body(self, node, frame, children=None):
-        """Dump the function def of a macro or call block."""
-        frame = self.function_scoping(node, frame, children)
-        # macros are delayed, they never require output checks
-        frame.require_output_check = False
-        args = frame.arguments
-        # XXX: this is an ugly fix for the loop nesting bug
-        # (tests.test_old_bugs.test_loop_call_bug).  This works around
-        # a identifier nesting problem we have in general.  It's just more
-        # likely to happen in loops which is why we work around it.  The
-        # real solution would be "nonlocal" all the identifiers that are
-        # leaking into a new python frame and might be used both unassigned
-        # and assigned.
-        if 'loop' in frame.identifiers.declared:
-            args = args + ['l_loop=l_loop']
-        self.writeline('def macro(%s):' % ', '.join(args), node)
-        self.indent()
-        self.buffer(frame)
-        self.pull_locals(frame)
-        self.blockvisit(node.body, frame)
-        self.return_buffer_contents(frame)
-        self.outdent()
-        return frame
-
-    def macro_def(self, node, frame):
-        """Dump the macro definition for the def created by macro_body."""
-        arg_tuple = ', '.join(repr(x.name) for x in node.args)
-        name = getattr(node, 'name', None)
-        if len(node.args) == 1:
-            arg_tuple += ','
-        self.write('Macro(environment, macro, %r, (%s), (' %
-                   (name, arg_tuple))
-        for arg in node.defaults:
-            self.visit(arg, frame)
-            self.write(', ')
-        self.write('), %r, %r, %r)' % (
-            bool(frame.accesses_kwargs),
-            bool(frame.accesses_varargs),
-            bool(frame.accesses_caller)
-        ))
-
-    def position(self, node):
-        """Return a human readable position for the node."""
-        rv = 'line %d' % node.lineno
-        if self.name is not None:
-            rv += ' in ' + repr(self.name)
-        return rv
-
-    # -- Statement Visitors
-
-    def visit_Template(self, node, frame=None):
-        assert frame is None, 'no root frame allowed'
-        eval_ctx = EvalContext(self.environment, self.name)
-
-        from ambari_jinja2.runtime import __all__ as exported
-        self.writeline('from __future__ import division')
-        self.writeline('from ambari_jinja2.runtime import ' + ', '.join(exported))
-        if not unoptimize_before_dead_code:
-            self.writeline('dummy = lambda *x: None')
-
-        # if we want a deferred initialization we cannot move the
-        # environment into a local name
-        envenv = not self.defer_init and ', environment=environment' or ''
-
-        # do we have an extends tag at all?  If not, we can save some
-        # overhead by just not processing any inheritance code.
-        have_extends = node.find(nodes.Extends) is not None
-
-        # find all blocks
-        for block in node.find_all(nodes.Block):
-            if block.name in self.blocks:
-                self.fail('block %r defined twice' % block.name, block.lineno)
-            self.blocks[block.name] = block
-
-        # find all imports and import them
-        for import_ in node.find_all(nodes.ImportedName):
-            if import_.importname not in self.import_aliases:
-                imp = import_.importname
-                self.import_aliases[imp] = alias = self.temporary_identifier()
-                if '.' in imp:
-                    module, obj = imp.rsplit('.', 1)
-                    self.writeline('from %s import %s as %s' %
-                                   (module, obj, alias))
-                else:
-                    self.writeline('import %s as %s' % (imp, alias))
-
-        # add the load name
-        self.writeline('name = %r' % self.name)
-
-        # generate the root render function.
-        self.writeline('def root(context%s):' % envenv, extra=1)
-
-        # process the root
-        frame = Frame(eval_ctx)
-        frame.inspect(node.body)
-        frame.toplevel = frame.rootlevel = True
-        frame.require_output_check = have_extends and not self.has_known_extends
-        self.indent()
-        if have_extends:
-            self.writeline('parent_template = None')
-        if 'self' in find_undeclared(node.body, ('self',)):
-            frame.identifiers.add_special('self')
-            self.writeline('l_self = TemplateReference(context)')
-        self.pull_locals(frame)
-        self.pull_dependencies(node.body)
-        self.blockvisit(node.body, frame)
-        self.outdent()
-
-        # make sure that the parent root is called.
-        if have_extends:
-            if not self.has_known_extends:
-                self.indent()
-                self.writeline('if parent_template is not None:')
-            self.indent()
-            self.writeline('for event in parent_template.'
-                           'root_render_func(context):')
-            self.indent()
-            self.writeline('yield event')
-            self.outdent(2 + (not self.has_known_extends))
-
-        # at this point we now have the blocks collected and can visit them too.
-        for name, block in self.blocks.iteritems():
-            block_frame = Frame(eval_ctx)
-            block_frame.inspect(block.body)
-            block_frame.block = name
-            self.writeline('def block_%s(context%s):' % (name, envenv),
-                           block, 1)
-            self.indent()
-            undeclared = find_undeclared(block.body, ('self', 'super'))
-            if 'self' in undeclared:
-                block_frame.identifiers.add_special('self')
-                self.writeline('l_self = TemplateReference(context)')
-            if 'super' in undeclared:
-                block_frame.identifiers.add_special('super')
-                self.writeline('l_super = context.super(%r, '
-                               'block_%s)' % (name, name))
-            self.pull_locals(block_frame)
-            self.pull_dependencies(block.body)
-            self.blockvisit(block.body, block_frame)
-            self.outdent()
-
-        self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
-                                                   for x in self.blocks),
-                       extra=1)
-
-        # add a function that returns the debug info
-        self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
-                                                    in self.debug_info))
-
-    def visit_Block(self, node, frame):
-        """Call a block and register it for the template."""
-        level = 1
-        if frame.toplevel:
-            # if we know that we are a child template, there is no need to
-            # check if we are one
-            if self.has_known_extends:
-                return
-            if self.extends_so_far > 0:
-                self.writeline('if parent_template is None:')
-                self.indent()
-                level += 1
-        context = node.scoped and 'context.derived(locals())' or 'context'
-        self.writeline('for event in context.blocks[%r][0](%s):' % (
-                       node.name, context), node)
-        self.indent()
-        self.simple_write('event', frame)
-        self.outdent(level)
-
-    def visit_Extends(self, node, frame):
-        """Calls the extender."""
-        if not frame.toplevel:
-            self.fail('cannot use extend from a non top-level scope',
-                      node.lineno)
-
-        # if the number of extends statements in general is zero so
-        # far, we don't have to add a check if something extended
-        # the template before this one.
-        if self.extends_so_far > 0:
-
-            # if we have a known extends we just add a template runtime
-            # error into the generated code.  We could catch that at compile
-            # time too, but i welcome it not to confuse users by throwing the
-            # same error at different times just "because we can".
-            if not self.has_known_extends:
-                self.writeline('if parent_template is not None:')
-                self.indent()
-            self.writeline('raise TemplateRuntimeError(%r)' %
-                           'extended multiple times')
-            self.outdent()
-
-            # if we have a known extends already we don't need that code here
-            # as we know that the template execution will end here.
-            if self.has_known_extends:
-                raise CompilerExit()
-
-        self.writeline('parent_template = environment.get_template(', node)
-        self.visit(node.template, frame)
-        self.write(', %r)' % self.name)
-        self.writeline('for name, parent_block in parent_template.'
-                       'blocks.%s():' % dict_item_iter)
-        self.indent()
-        self.writeline('context.blocks.setdefault(name, []).'
-                       'append(parent_block)')
-        self.outdent()
-
-        # if this extends statement was in the root level we can take
-        # advantage of that information and simplify the generated code
-        # in the top level from this point onwards
-        if frame.rootlevel:
-            self.has_known_extends = True
-
-        # and now we have one more
-        self.extends_so_far += 1
-
-    def visit_Include(self, node, frame):
-        """Handles includes."""
-        if node.with_context:
-            self.unoptimize_scope(frame)
-        if node.ignore_missing:
-            self.writeline('try:')
-            self.indent()
-
-        func_name = 'get_or_select_template'
-        if isinstance(node.template, nodes.Const):
-            if isinstance(node.template.value, basestring):
-                func_name = 'get_template'
-            elif isinstance(node.template.value, (tuple, list)):
-                func_name = 'select_template'
-        elif isinstance(node.template, (nodes.Tuple, nodes.List)):
-            func_name = 'select_template'
-
-        self.writeline('template = environment.%s(' % func_name, node)
-        self.visit(node.template, frame)
-        self.write(', %r)' % self.name)
-        if node.ignore_missing:
-            self.outdent()
-            self.writeline('except TemplateNotFound:')
-            self.indent()
-            self.writeline('pass')
-            self.outdent()
-            self.writeline('else:')
-            self.indent()
-
-        if node.with_context:
-            self.writeline('for event in template.root_render_func('
-                           'template.new_context(context.parent, True, '
-                           'locals())):')
-        else:
-            self.writeline('for event in template.module._body_stream:')
-
-        self.indent()
-        self.simple_write('event', frame)
-        self.outdent()
-
-        if node.ignore_missing:
-            self.outdent()
-
-    def visit_Import(self, node, frame):
-        """Visit regular imports."""
-        if node.with_context:
-            self.unoptimize_scope(frame)
-        self.writeline('l_%s = ' % node.target, node)
-        if frame.toplevel:
-            self.write('context.vars[%r] = ' % node.target)
-        self.write('environment.get_template(')
-        self.visit(node.template, frame)
-        self.write(', %r).' % self.name)
-        if node.with_context:
-            self.write('make_module(context.parent, True, locals())')
-        else:
-            self.write('module')
-        if frame.toplevel and not node.target.startswith('_'):
-            self.writeline('context.exported_vars.discard(%r)' % node.target)
-        frame.assigned_names.add(node.target)
-
-    def visit_FromImport(self, node, frame):
-        """Visit named imports."""
-        self.newline(node)
-        self.write('included_template = environment.get_template(')
-        self.visit(node.template, frame)
-        self.write(', %r).' % self.name)
-        if node.with_context:
-            self.write('make_module(context.parent, True)')
-        else:
-            self.write('module')
-
-        var_names = []
-        discarded_names = []
-        for name in node.names:
-            if isinstance(name, tuple):
-                name, alias = name
-            else:
-                alias = name
-            self.writeline('l_%s = getattr(included_template, '
-                           '%r, missing)' % (alias, name))
-            self.writeline('if l_%s is missing:' % alias)
-            self.indent()
-            self.writeline('l_%s = environment.undefined(%r %% '
-                           'included_template.__name__, '
-                           'name=%r)' %
-                           (alias, 'the template %%r (imported on %s) does '
-                           'not export the requested name %s' % (
-                                self.position(node),
-                                repr(name)
-                           ), name))
-            self.outdent()
-            if frame.toplevel:
-                var_names.append(alias)
-                if not alias.startswith('_'):
-                    discarded_names.append(alias)
-            frame.assigned_names.add(alias)
-
-        if var_names:
-            if len(var_names) == 1:
-                name = var_names[0]
-                self.writeline('context.vars[%r] = l_%s' % (name, name))
-            else:
-                self.writeline('context.vars.update({%s})' % ', '.join(
-                    '%r: l_%s' % (name, name) for name in var_names
-                ))
-        if discarded_names:
-            if len(discarded_names) == 1:
-                self.writeline('context.exported_vars.discard(%r)' %
-                               discarded_names[0])
-            else:
-                self.writeline('context.exported_vars.difference_'
-                               'update((%s))' % ', '.join(map(repr, discarded_names)))
-
-    def visit_For(self, node, frame):
-        # when calculating the nodes for the inner frame we have to exclude
-        # the iterator contents from it
-        children = node.iter_child_nodes(exclude=('iter',))
-        if node.recursive:
-            loop_frame = self.function_scoping(node, frame, children,
-                                               find_special=False)
-        else:
-            loop_frame = frame.inner()
-            loop_frame.inspect(children)
-
-        # try to figure out if we have an extended loop.  An extended loop
-        # is necessary if the loop is in recursive mode if the special loop
-        # variable is accessed in the body.
-        extended_loop = node.recursive or 'loop' in \
-                        find_undeclared(node.iter_child_nodes(
-                            only=('body',)), ('loop',))
-
-        # if we don't have an recursive loop we have to find the shadowed
-        # variables at that point.  Because loops can be nested but the loop
-        # variable is a special one we have to enforce aliasing for it.
-        if not node.recursive:
-            aliases = self.push_scope(loop_frame, ('loop',))
-
-        # otherwise we set up a buffer and add a function def
-        else:
-            self.writeline('def loop(reciter, loop_render_func):', node)
-            self.indent()
-            self.buffer(loop_frame)
-            aliases = {}
-
-        # make sure the loop variable is a special one and raise a template
-        # assertion error if a loop tries to write to loop
-        if extended_loop:
-            loop_frame.identifiers.add_special('loop')
-        for name in node.find_all(nodes.Name):
-            if name.ctx == 'store' and name.name == 'loop':
-                self.fail('Can\'t assign to special loop variable '
-                          'in for-loop target', name.lineno)
-
-        self.pull_locals(loop_frame)
-        if node.else_:
-            iteration_indicator = self.temporary_identifier()
-            self.writeline('%s = 1' % iteration_indicator)
-
-        # Create a fake parent loop if the else or test section of a
-        # loop is accessing the special loop variable and no parent loop
-        # exists.
-        if 'loop' not in aliases and 'loop' in find_undeclared(
-           node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
-            self.writeline("l_loop = environment.undefined(%r, name='loop')" %
-                ("'loop' is undefined. the filter section of a loop as well "
-                 "as the else block doesn't have access to the special 'loop'"
-                 " variable of the current loop.  Because there is no parent "
-                 "loop it's undefined.  Happened in loop on %s" %
-                 self.position(node)))
-
-        self.writeline('for ', node)
-        self.visit(node.target, loop_frame)
-        self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
-
-        # if we have an extened loop and a node test, we filter in the
-        # "outer frame".
-        if extended_loop and node.test is not None:
-            self.write('(')
-            self.visit(node.target, loop_frame)
-            self.write(' for ')
-            self.visit(node.target, loop_frame)
-            self.write(' in ')
-            if node.recursive:
-                self.write('reciter')
-            else:
-                self.visit(node.iter, loop_frame)
-            self.write(' if (')
-            test_frame = loop_frame.copy()
-            self.visit(node.test, test_frame)
-            self.write('))')
-
-        elif node.recursive:
-            self.write('reciter')
-        else:
-            self.visit(node.iter, loop_frame)
-
-        if node.recursive:
-            self.write(', recurse=loop_render_func):')
-        else:
-            self.write(extended_loop and '):' or ':')
-
-        # tests in not extended loops become a continue
-        if not extended_loop and node.test is not None:
-            self.indent()
-            self.writeline('if not ')
-            self.visit(node.test, loop_frame)
-            self.write(':')
-            self.indent()
-            self.writeline('continue')
-            self.outdent(2)
-
-        self.indent()
-        self.blockvisit(node.body, loop_frame)
-        if node.else_:
-            self.writeline('%s = 0' % iteration_indicator)
-        self.outdent()
-
-        if node.else_:
-            self.writeline('if %s:' % iteration_indicator)
-            self.indent()
-            self.blockvisit(node.else_, loop_frame)
-            self.outdent()
-
-        # reset the aliases if there are any.
-        if not node.recursive:
-            self.pop_scope(aliases, loop_frame)
-
-        # if the node was recursive we have to return the buffer contents
-        # and start the iteration code
-        if node.recursive:
-            self.return_buffer_contents(loop_frame)
-            self.outdent()
-            self.start_write(frame, node)
-            self.write('loop(')
-            self.visit(node.iter, frame)
-            self.write(', loop)')
-            self.end_write(frame)
-
-    def visit_If(self, node, frame):
-        if_frame = frame.soft()
-        self.writeline('if ', node)
-        self.visit(node.test, if_frame)
-        self.write(':')
-        self.indent()
-        self.blockvisit(node.body, if_frame)
-        self.outdent()
-        if node.else_:
-            self.writeline('else:')
-            self.indent()
-            self.blockvisit(node.else_, if_frame)
-            self.outdent()
-
-    def visit_Macro(self, node, frame):
-        macro_frame = self.macro_body(node, frame)
-        self.newline()
-        if frame.toplevel:
-            if not node.name.startswith('_'):
-                self.write('context.exported_vars.add(%r)' % node.name)
-            self.writeline('context.vars[%r] = ' % node.name)
-        self.write('l_%s = ' % node.name)
-        self.macro_def(node, macro_frame)
-        frame.assigned_names.add(node.name)
-
-    def visit_CallBlock(self, node, frame):
-        children = node.iter_child_nodes(exclude=('call',))
-        call_frame = self.macro_body(node, frame, children)
-        self.writeline('caller = ')
-        self.macro_def(node, call_frame)
-        self.start_write(frame, node)
-        self.visit_Call(node.call, call_frame, forward_caller=True)
-        self.end_write(frame)
-
-    def visit_FilterBlock(self, node, frame):
-        filter_frame = frame.inner()
-        filter_frame.inspect(node.iter_child_nodes())
-        aliases = self.push_scope(filter_frame)
-        self.pull_locals(filter_frame)
-        self.buffer(filter_frame)
-        self.blockvisit(node.body, filter_frame)
-        self.start_write(frame, node)
-        self.visit_Filter(node.filter, filter_frame)
-        self.end_write(frame)
-        self.pop_scope(aliases, filter_frame)
-
-    def visit_ExprStmt(self, node, frame):
-        self.newline(node)
-        self.visit(node.node, frame)
-
-    def visit_Output(self, node, frame):
-        # if we have a known extends statement, we don't output anything
-        # if we are in a require_output_check section
-        if self.has_known_extends and frame.require_output_check:
-            return
-
-        if self.environment.finalize:
-            finalize = lambda x: unicode(self.environment.finalize(x))
-        else:
-            finalize = unicode
-
-        # if we are inside a frame that requires output checking, we do so
-        outdent_later = False
-        if frame.require_output_check:
-            self.writeline('if parent_template is None:')
-            self.indent()
-            outdent_later = True
-
-        # try to evaluate as many chunks as possible into a static
-        # string at compile time.
-        body = []
-        for child in node.nodes:
-            try:
-                const = child.as_const(frame.eval_ctx)
-            except nodes.Impossible:
-                body.append(child)
-                continue
-            # the frame can't be volatile here, becaus otherwise the
-            # as_const() function would raise an Impossible exception
-            # at that point.
-            try:
-                if frame.eval_ctx.autoescape:
-                    if hasattr(const, '__html__'):
-                        const = const.__html__()
-                    else:
-                        const = escape(const)
-                const = finalize(const)
-            except:
-                # if something goes wrong here we evaluate the node
-                # at runtime for easier debugging
-                body.append(child)
-                continue
-            if body and isinstance(body[-1], list):
-                body[-1].append(const)
-            else:
-                body.append([const])
-
-        # if we have less than 3 nodes or a buffer we yield or extend/append
-        if len(body) < 3 or frame.buffer is not None:
-            if frame.buffer is not None:
-                # for one item we append, for more we extend
-                if len(body) == 1:
-                    self.writeline('%s.append(' % frame.buffer)
-                else:
-                    self.writeline('%s.extend((' % frame.buffer)
-                self.indent()
-            for item in body:
-                if isinstance(item, list):
-                    val = repr(concat(item))
-                    if frame.buffer is None:
-                        self.writeline('yield ' + val)
-                    else:
-                        self.writeline(val + ', ')
-                else:
-                    if frame.buffer is None:
-                        self.writeline('yield ', item)
-                    else:
-                        self.newline(item)
-                    close = 1
-                    if frame.eval_ctx.volatile:
-                        self.write('(context.eval_ctx.autoescape and'
-                                   ' escape or to_string)(')
-                    elif frame.eval_ctx.autoescape:
-                        self.write('escape(')
-                    else:
-                        self.write('to_string(')
-                    if self.environment.finalize is not None:
-                        self.write('environment.finalize(')
-                        close += 1
-                    self.visit(item, frame)
-                    self.write(')' * close)
-                    if frame.buffer is not None:
-                        self.write(', ')
-            if frame.buffer is not None:
-                # close the open parentheses
-                self.outdent()
-                self.writeline(len(body) == 1 and ')' or '))')
-
-        # otherwise we create a format string as this is faster in that case
-        else:
-            format = []
-            arguments = []
-            for item in body:
-                if isinstance(item, list):
-                    format.append(concat(item).replace('%', '%%'))
-                else:
-                    format.append('%s')
-                    arguments.append(item)
-            self.writeline('yield ')
-            self.write(repr(concat(format)) + ' % (')
-            idx = -1
-            self.indent()
-            for argument in arguments:
-                self.newline(argument)
-                close = 0
-                if frame.eval_ctx.volatile:
-                    self.write('(context.eval_ctx.autoescape and'
-                               ' escape or to_string)(')
-                    close += 1
-                elif frame.eval_ctx.autoescape:
-                    self.write('escape(')
-                    close += 1
-                if self.environment.finalize is not None:
-                    self.write('environment.finalize(')
-                    close += 1
-                self.visit(argument, frame)
-                self.write(')' * close + ', ')
-            self.outdent()
-            self.writeline(')')
-
-        if outdent_later:
-            self.outdent()
-
-    def visit_Assign(self, node, frame):
-        self.newline(node)
-        # toplevel assignments however go into the local namespace and
-        # the current template's context.  We create a copy of the frame
-        # here and add a set so that the Name visitor can add the assigned
-        # names here.
-        if frame.toplevel:
-            assignment_frame = frame.copy()
-            assignment_frame.toplevel_assignments = set()
-        else:
-            assignment_frame = frame
-        self.visit(node.target, assignment_frame)
-        self.write(' = ')
-        self.visit(node.node, frame)
-
-        # make sure toplevel assignments are added to the context.
-        if frame.toplevel:
-            public_names = [x for x in assignment_frame.toplevel_assignments
-                            if not x.startswith('_')]
-            if len(assignment_frame.toplevel_assignments) == 1:
-                name = next(iter(assignment_frame.toplevel_assignments))
-                self.writeline('context.vars[%r] = l_%s' % (name, name))
-            else:
-                self.writeline('context.vars.update({')
-                for idx, name in enumerate(assignment_frame.toplevel_assignments):
-                    if idx:
-                        self.write(', ')
-                    self.write('%r: l_%s' % (name, name))
-                self.write('})')
-            if public_names:
-                if len(public_names) == 1:
-                    self.writeline('context.exported_vars.add(%r)' %
-                                   public_names[0])
-                else:
-                    self.writeline('context.exported_vars.update((%s))' %
-                                   ', '.join(map(repr, public_names)))
-
-    # -- Expression Visitors
-
-    def visit_Name(self, node, frame):
-        if node.ctx == 'store' and frame.toplevel:
-            frame.toplevel_assignments.add(node.name)
-        self.write('l_' + node.name)
-        frame.assigned_names.add(node.name)
-
-    def visit_Const(self, node, frame):
-        val = node.value
-        if isinstance(val, float):
-            self.write(str(val))
-        else:
-            self.write(repr(val))
-
-    def visit_TemplateData(self, node, frame):
-        try:
-            self.write(repr(node.as_const(frame.eval_ctx)))
-        except nodes.Impossible:
-            self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
-                       % node.data)
-
-    def visit_Tuple(self, node, frame):
-        self.write('(')
-        idx = -1
-        for idx, item in enumerate(node.items):
-            if idx:
-                self.write(', ')
-            self.visit(item, frame)
-        self.write(idx == 0 and ',)' or ')')
-
-    def visit_List(self, node, frame):
-        self.write('[')
-        for idx, item in enumerate(node.items):
-            if idx:
-                self.write(', ')
-            self.visit(item, frame)
-        self.write(']')
-
-    def visit_Dict(self, node, frame):
-        self.write('{')
-        for idx, item in enumerate(node.items):
-            if idx:
-                self.write(', ')
-            self.visit(item.key, frame)
-            self.write(': ')
-            self.visit(item.value, frame)
-        self.write('}')
-
-    def binop(operator):
-        def visitor(self, node, frame):
-            self.write('(')
-            self.visit(node.left, frame)
-            self.write(' %s ' % operator)
-            self.visit(node.right, frame)
-            self.write(')')
-        return visitor
-
-    def uaop(operator):
-        def visitor(self, node, frame):
-            self.write('(' + operator)
-            self.visit(node.node, frame)
-            self.write(')')
-        return visitor
-
-    visit_Add = binop('+')
-    visit_Sub = binop('-')
-    visit_Mul = binop('*')
-    visit_Div = binop('/')
-    visit_FloorDiv = binop('//')
-    visit_Pow = binop('**')
-    visit_Mod = binop('%')
-    visit_And = binop('and')
-    visit_Or = binop('or')
-    visit_Pos = uaop('+')
-    visit_Neg = uaop('-')
-    visit_Not = uaop('not ')
-    del binop, uaop
-
-    def visit_Concat(self, node, frame):
-        if frame.eval_ctx.volatile:
-            func_name = '(context.eval_ctx.volatile and' \
-                        ' markup_join or unicode_join)'
-        elif frame.eval_ctx.autoescape:
-            func_name = 'markup_join'
-        else:
-            func_name = 'unicode_join'
-        self.write('%s((' % func_name)
-        for arg in node.nodes:
-            self.visit(arg, frame)
-            self.write(', ')
-        self.write('))')
-
-    def visit_Compare(self, node, frame):
-        self.visit(node.expr, frame)
-        for op in node.ops:
-            self.visit(op, frame)
-
-    def visit_Operand(self, node, frame):
-        self.write(' %s ' % operators[node.op])
-        self.visit(node.expr, frame)
-
-    def visit_Getattr(self, node, frame):
-        self.write('environment.getattr(')
-        self.visit(node.node, frame)
-        self.write(', %r)' % node.attr)
-
-    def visit_Getitem(self, node, frame):
-        # slices bypass the environment getitem method.
-        if isinstance(node.arg, nodes.Slice):
-            self.visit(node.node, frame)
-            self.write('[')
-            self.visit(node.arg, frame)
-            self.write(']')
-        else:
-            self.write('environment.getitem(')
-            self.visit(node.node, frame)
-            self.write(', ')
-            self.visit(node.arg, frame)
-            self.write(')')
-
-    def visit_Slice(self, node, frame):
-        if node.start is not None:
-            self.visit(node.start, frame)
-        self.write(':')
-        if node.stop is not None:
-            self.visit(node.stop, frame)
-        if node.step is not None:
-            self.write(':')
-            self.visit(node.step, frame)
-
-    def visit_Filter(self, node, frame):
-        self.write(self.filters[node.name] + '(')
-        func = self.environment.filters.get(node.name)
-        if func is None:
-            self.fail('no filter named %r' % node.name, node.lineno)
-        if getattr(func, 'contextfilter', False):
-            self.write('context, ')
-        elif getattr(func, 'evalcontextfilter', False):
-            self.write('context.eval_ctx, ')
-        elif getattr(func, 'environmentfilter', False):
-            self.write('environment, ')
-
-        # if the filter node is None we are inside a filter block
-        # and want to write to the current buffer
-        if node.node is not None:
-            self.visit(node.node, frame)
-        elif frame.eval_ctx.volatile:
-            self.write('(context.eval_ctx.autoescape and'
-                       ' Markup(concat(%s)) or concat(%s))' %
-                       (frame.buffer, frame.buffer))
-        elif frame.eval_ctx.autoescape:
-            self.write('Markup(concat(%s))' % frame.buffer)
-        else:
-            self.write('concat(%s)' % frame.buffer)
-        self.signature(node, frame)
-        self.write(')')
-
-    def visit_Test(self, node, frame):
-        self.write(self.tests[node.name] + '(')
-        if node.name not in self.environment.tests:
-            self.fail('no test named %r' % node.name, node.lineno)
-        self.visit(node.node, frame)
-        self.signature(node, frame)
-        self.write(')')
-
-    def visit_CondExpr(self, node, frame):
-        def write_expr2():
-            if node.expr2 is not None:
-                return self.visit(node.expr2, frame)
-            self.write('environment.undefined(%r)' % ('the inline if-'
-                       'expression on %s evaluated to false and '
-                       'no else section was defined.' % self.position(node)))
-
-        if not have_condexpr:
-            self.write('((')
-            self.visit(node.test, frame)
-            self.write(') and (')
-            self.visit(node.expr1, frame)
-            self.write(',) or (')
-            write_expr2()
-            self.write(',))[0]')
-        else:
-            self.write('(')
-            self.visit(node.expr1, frame)
-            self.write(' if ')
-            self.visit(node.test, frame)
-            self.write(' else ')
-            write_expr2()
-            self.write(')')
-
-    def visit_Call(self, node, frame, forward_caller=False):
-        if self.environment.sandboxed:
-            self.write('environment.call(context, ')
-        else:
-            self.write('context.call(')
-        self.visit(node.node, frame)
-        extra_kwargs = forward_caller and {'caller': 'caller'} or None
-        self.signature(node, frame, extra_kwargs)
-        self.write(')')
-
-    def visit_Keyword(self, node, frame):
-        self.write(node.key + '=')
-        self.visit(node.value, frame)
-
-    # -- Unused nodes for extensions
-
-    def visit_MarkSafe(self, node, frame):
-        self.write('Markup(')
-        self.visit(node.expr, frame)
-        self.write(')')
-
-    def visit_MarkSafeIfAutoescape(self, node, frame):
-        self.write('(context.eval_ctx.autoescape and Markup or identity)(')
-        self.visit(node.expr, frame)
-        self.write(')')
-
-    def visit_EnvironmentAttribute(self, node, frame):
-        self.write('environment.' + node.name)
-
-    def visit_ExtensionAttribute(self, node, frame):
-        self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
-
-    def visit_ImportedName(self, node, frame):
-        self.write(self.import_aliases[node.importname])
-
-    def visit_InternalName(self, node, frame):
-        self.write(node.name)
-
-    def visit_ContextReference(self, node, frame):
-        self.write('context')
-
-    def visit_Continue(self, node, frame):
-        self.writeline('continue', node)
-
-    def visit_Break(self, node, frame):
-        self.writeline('break', node)
-
-    def visit_Scope(self, node, frame):
-        scope_frame = frame.inner()
-        scope_frame.inspect(node.iter_child_nodes())
-        aliases = self.push_scope(scope_frame)
-        self.pull_locals(scope_frame)
-        self.blockvisit(node.body, scope_frame)
-        self.pop_scope(aliases, scope_frame)
-
-    def visit_EvalContextModifier(self, node, frame):
-        for keyword in node.options:
-            self.writeline('context.eval_ctx.%s = ' % keyword.key)
-            self.visit(keyword.value, frame)
-            try:
-                val = keyword.value.as_const(frame.eval_ctx)
-            except nodes.Impossible:
-                frame.eval_ctx.volatile = True
-            else:
-                setattr(frame.eval_ctx, keyword.key, val)
-
-    def visit_ScopedEvalContextModifier(self, node, frame):
-        old_ctx_name = self.temporary_identifier()
-        safed_ctx = frame.eval_ctx.save()
-        self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
-        self.visit_EvalContextModifier(node, frame)
-        for child in node.body:
-            self.visit(child, frame)
-        frame.eval_ctx.revert(safed_ctx)
-        self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py
deleted file mode 100644
index cab203c..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja.constants
-    ~~~~~~~~~~~~~~~
-
-    Various constants.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-#: list of lorem ipsum words used by the lipsum() helper function
-LOREM_IPSUM_WORDS = u'''\
-a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
-auctor augue bibendum blandit class commodo condimentum congue consectetuer
-consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
-diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
-elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
-faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
-hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
-justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
-luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
-mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
-nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
-penatibus per pharetra phasellus placerat platea porta porttitor posuere
-potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
-ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
-sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
-tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
-ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
-viverra volutpat vulputate'''

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py
deleted file mode 100644
index d48a958..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py
+++ /dev/null
@@ -1,308 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.debug
-    ~~~~~~~~~~~~
-
-    Implements the debug interface for Jinja.  This module does some pretty
-    ugly stuff with the Python traceback system in order to achieve tracebacks
-    with correct line numbers, locals and contents.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import sys
-import traceback
-from ambari_jinja2.utils import CodeType, missing, internal_code
-from ambari_jinja2.exceptions import TemplateSyntaxError
-
-
-# how does the raise helper look like?
-try:
-    exec "raise TypeError, 'foo'"
-except SyntaxError:
-    raise_helper = 'raise __jinja_exception__[1]'
-except TypeError:
-    raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]'
-
-
-class TracebackFrameProxy(object):
-    """Proxies a traceback frame."""
-
-    def __init__(self, tb):
-        self.tb = tb
-
-    def _set_tb_next(self, next):
-        if tb_set_next is not None:
-            tb_set_next(self.tb, next and next.tb or None)
-        self._tb_next = next
-
-    def _get_tb_next(self):
-        return self._tb_next
-
-    tb_next = property(_get_tb_next, _set_tb_next)
-    del _get_tb_next, _set_tb_next
-
-    @property
-    def is_jinja_frame(self):
-        return '__jinja_template__' in self.tb.tb_frame.f_globals
-
-    def __getattr__(self, name):
-        return getattr(self.tb, name)
-
-
-class ProcessedTraceback(object):
-    """Holds a Jinja preprocessed traceback for priting or reraising."""
-
-    def __init__(self, exc_type, exc_value, frames):
-        assert frames, 'no frames for this traceback?'
-        self.exc_type = exc_type
-        self.exc_value = exc_value
-        self.frames = frames
-
-    def chain_frames(self):
-        """Chains the frames.  Requires ctypes or the debugsupport extension."""
-        prev_tb = None
-        for tb in self.frames:
-            if prev_tb is not None:
-                prev_tb.tb_next = tb
-            prev_tb = tb
-        prev_tb.tb_next = None
-
-    def render_as_text(self, limit=None):
-        """Return a string with the traceback."""
-        lines = traceback.format_exception(self.exc_type, self.exc_value,
-                                           self.frames[0], limit=limit)
-        return ''.join(lines).rstrip()
-
-    def render_as_html(self, full=False):
-        """Return a unicode string with the traceback as rendered HTML."""
-        from ambari_jinja2.debugrenderer import render_traceback
-        return u'%s\n\n<!--\n%s\n-->' % (
-            render_traceback(self, full=full),
-            self.render_as_text().decode('utf-8', 'replace')
-        )
-
-    @property
-    def is_template_syntax_error(self):
-        """`True` if this is a template syntax error."""
-        return isinstance(self.exc_value, TemplateSyntaxError)
-
-    @property
-    def exc_info(self):
-        """Exception info tuple with a proxy around the frame objects."""
-        return self.exc_type, self.exc_value, self.frames[0]
-
-    @property
-    def standard_exc_info(self):
-        """Standard python exc_info for re-raising"""
-        return self.exc_type, self.exc_value, self.frames[0].tb
-
-
-def make_traceback(exc_info, source_hint=None):
-    """Creates a processed traceback object from the exc_info."""
-    exc_type, exc_value, tb = exc_info
-    if isinstance(exc_value, TemplateSyntaxError):
-        exc_info = translate_syntax_error(exc_value, source_hint)
-        initial_skip = 0
-    else:
-        initial_skip = 1
-    return translate_exception(exc_info, initial_skip)
-
-
-def translate_syntax_error(error, source=None):
-    """Rewrites a syntax error to please traceback systems."""
-    error.source = source
-    error.translated = True
-    exc_info = (error.__class__, error, None)
-    filename = error.filename
-    if filename is None:
-        filename = '<unknown>'
-    return fake_exc_info(exc_info, filename, error.lineno)
-
-
-def translate_exception(exc_info, initial_skip=0):
-    """If passed an exc_info it will automatically rewrite the exceptions
-    all the way down to the correct line numbers and frames.
-    """
-    tb = exc_info[2]
-    frames = []
-
-    # skip some internal frames if wanted
-    for x in xrange(initial_skip):
-        if tb is not None:
-            tb = tb.tb_next
-    initial_tb = tb
-
-    while tb is not None:
-        # skip frames decorated with @internalcode.  These are internal
-        # calls we can't avoid and that are useless in template debugging
-        # output.
-        if tb.tb_frame.f_code in internal_code:
-            tb = tb.tb_next
-            continue
-
-        # save a reference to the next frame if we override the current
-        # one with a faked one.
-        next = tb.tb_next
-
-        # fake template exceptions
-        template = tb.tb_frame.f_globals.get('__jinja_template__')
-        if template is not None:
-            lineno = template.get_corresponding_lineno(tb.tb_lineno)
-            tb = fake_exc_info(exc_info[:2] + (tb,), template.filename,
-                               lineno)[2]
-
-        frames.append(TracebackFrameProxy(tb))
-        tb = next
-
-    # if we don't have any exceptions in the frames left, we have to
-    # reraise it unchanged.
-    # XXX: can we backup here?  when could this happen?
-    if not frames:
-        raise exc_info[0], exc_info[1], exc_info[2]
-
-    traceback = ProcessedTraceback(exc_info[0], exc_info[1], frames)
-    if tb_set_next is not None:
-        traceback.chain_frames()
-    return traceback
-
-
-def fake_exc_info(exc_info, filename, lineno):
-    """Helper for `translate_exception`."""
-    exc_type, exc_value, tb = exc_info
-
-    # figure the real context out
-    if tb is not None:
-        real_locals = tb.tb_frame.f_locals.copy()
-        ctx = real_locals.get('context')
-        if ctx:
-            locals = ctx.get_all()
-        else:
-            locals = {}
-        for name, value in real_locals.iteritems():
-            if name.startswith('l_') and value is not missing:
-                locals[name[2:]] = value
-
-        # if there is a local called __jinja_exception__, we get
-        # rid of it to not break the debug functionality.
-        locals.pop('__jinja_exception__', None)
-    else:
-        locals = {}
-
-    # assamble fake globals we need
-    globals = {
-        '__name__':             filename,
-        '__file__':             filename,
-        '__jinja_exception__':  exc_info[:2],
-
-        # we don't want to keep the reference to the template around
-        # to not cause circular dependencies, but we mark it as Jinja
-        # frame for the ProcessedTraceback
-        '__jinja_template__':   None
-    }
-
-    # and fake the exception
-    code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec')
-
-    # if it's possible, change the name of the code.  This won't work
-    # on some python environments such as google appengine
-    try:
-        if tb is None:
-            location = 'template'
-        else:
-            function = tb.tb_frame.f_code.co_name
-            if function == 'root':
-                location = 'top-level template code'
-            elif function.startswith('block_'):
-                location = 'block "%s"' % function[6:]
-            else:
-                location = 'template'
-        code = CodeType(0, code.co_nlocals, code.co_stacksize,
-                        code.co_flags, code.co_code, code.co_consts,
-                        code.co_names, code.co_varnames, filename,
-                        location, code.co_firstlineno,
-                        code.co_lnotab, (), ())
-    except:
-        pass
-
-    # execute the code and catch the new traceback
-    try:
-        exec code in globals, locals
-    except:
-        exc_info = sys.exc_info()
-        new_tb = exc_info[2].tb_next
-
-    # return without this frame
-    return exc_info[:2] + (new_tb,)
-
-
-def _init_ugly_crap():
-    """This function implements a few ugly things so that we can patch the
-    traceback objects.  The function returned allows resetting `tb_next` on
-    any python traceback object.
-    """
-    import ctypes
-    from types import TracebackType
-
-    # figure out side of _Py_ssize_t
-    if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
-        _Py_ssize_t = ctypes.c_int64
-    else:
-        _Py_ssize_t = ctypes.c_int
-
-    # regular python
-    class _PyObject(ctypes.Structure):
-        pass
-    _PyObject._fields_ = [
-        ('ob_refcnt', _Py_ssize_t),
-        ('ob_type', ctypes.POINTER(_PyObject))
-    ]
-
-    # python with trace
-    if hasattr(sys, 'getobjects'):
-        class _PyObject(ctypes.Structure):
-            pass
-        _PyObject._fields_ = [
-            ('_ob_next', ctypes.POINTER(_PyObject)),
-            ('_ob_prev', ctypes.POINTER(_PyObject)),
-            ('ob_refcnt', _Py_ssize_t),
-            ('ob_type', ctypes.POINTER(_PyObject))
-        ]
-
-    class _Traceback(_PyObject):
-        pass
-    _Traceback._fields_ = [
-        ('tb_next', ctypes.POINTER(_Traceback)),
-        ('tb_frame', ctypes.POINTER(_PyObject)),
-        ('tb_lasti', ctypes.c_int),
-        ('tb_lineno', ctypes.c_int)
-    ]
-
-    def tb_set_next(tb, next):
-        """Set the tb_next attribute of a traceback object."""
-        if not (isinstance(tb, TracebackType) and
-                (next is None or isinstance(next, TracebackType))):
-            raise TypeError('tb_set_next arguments must be traceback objects')
-        obj = _Traceback.from_address(id(tb))
-        if tb.tb_next is not None:
-            old = _Traceback.from_address(id(tb.tb_next))
-            old.ob_refcnt -= 1
-        if next is None:
-            obj.tb_next = ctypes.POINTER(_Traceback)()
-        else:
-            next = _Traceback.from_address(id(next))
-            next.ob_refcnt += 1
-            obj.tb_next = ctypes.pointer(next)
-
-    return tb_set_next
-
-
-# try to get a tb_set_next implementation
-try:
-    from ambari_jinja2._debugsupport import tb_set_next
-except ImportError:
-    try:
-        tb_set_next = _init_ugly_crap()
-    except:
-        tb_set_next = None
-del _init_ugly_crap

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py
deleted file mode 100644
index 566ebca..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2.defaults
-    ~~~~~~~~~~~~~~~
-
-    Jinja default filters and tags.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from ambari_jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
-
-
-# defaults for the parser / lexer
-BLOCK_START_STRING = '{%'
-BLOCK_END_STRING = '%}'
-VARIABLE_START_STRING = '{{'
-VARIABLE_END_STRING = '}}'
-COMMENT_START_STRING = '{#'
-COMMENT_END_STRING = '#}'
-LINE_STATEMENT_PREFIX = None
-LINE_COMMENT_PREFIX = None
-TRIM_BLOCKS = False
-NEWLINE_SEQUENCE = '\n'
-
-
-# default filters, tests and namespace
-from ambari_jinja2.filters import FILTERS as DEFAULT_FILTERS
-from ambari_jinja2.tests import TESTS as DEFAULT_TESTS
-DEFAULT_NAMESPACE = {
-    'range':        xrange,
-    'dict':         lambda **kw: kw,
-    'lipsum':       generate_lorem_ipsum,
-    'cycler':       Cycler,
-    'joiner':       Joiner
-}
-
-
-# export all constants
-__all__ = tuple(x for x in locals().keys() if x.isupper())


[49/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py
new file mode 100644
index 0000000..e728209
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/bccache.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.bccache
+    ~~~~~~~~~~~~~~
+
+    This module implements the bytecode cache system Jinja is optionally
+    using.  This is useful if you have very complex template situations and
+    the compiliation of all those templates slow down your application too
+    much.
+
+    Situations where this is useful are often forking web applications that
+    are initialized on the first request.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from os import path, listdir
+import marshal
+import tempfile
+import cPickle as pickle
+import fnmatch
+from cStringIO import StringIO
+try:
+    from hashlib import sha1
+except ImportError:
+    from sha import new as sha1
+from ambari_jinja2.utils import open_if_exists
+
+
+bc_version = 1
+bc_magic = 'j2'.encode('ascii') + pickle.dumps(bc_version, 2)
+
+
+class Bucket(object):
+    """Buckets are used to store the bytecode for one template.  It's created
+    and initialized by the bytecode cache and passed to the loading functions.
+
+    The buckets get an internal checksum from the cache assigned and use this
+    to automatically reject outdated cache material.  Individual bytecode
+    cache subclasses don't have to care about cache invalidation.
+    """
+
+    def __init__(self, environment, key, checksum):
+        self.environment = environment
+        self.key = key
+        self.checksum = checksum
+        self.reset()
+
+    def reset(self):
+        """Resets the bucket (unloads the bytecode)."""
+        self.code = None
+
+    def load_bytecode(self, f):
+        """Loads bytecode from a file or file like object."""
+        # make sure the magic header is correct
+        magic = f.read(len(bc_magic))
+        if magic != bc_magic:
+            self.reset()
+            return
+        # the source code of the file changed, we need to reload
+        checksum = pickle.load(f)
+        if self.checksum != checksum:
+            self.reset()
+            return
+        # now load the code.  Because marshal is not able to load
+        # from arbitrary streams we have to work around that
+        if isinstance(f, file):
+            self.code = marshal.load(f)
+        else:
+            self.code = marshal.loads(f.read())
+
+    def write_bytecode(self, f):
+        """Dump the bytecode into the file or file like object passed."""
+        if self.code is None:
+            raise TypeError('can\'t write empty bucket')
+        f.write(bc_magic)
+        pickle.dump(self.checksum, f, 2)
+        if isinstance(f, file):
+            marshal.dump(self.code, f)
+        else:
+            f.write(marshal.dumps(self.code))
+
+    def bytecode_from_string(self, string):
+        """Load bytecode from a string."""
+        self.load_bytecode(StringIO(string))
+
+    def bytecode_to_string(self):
+        """Return the bytecode as string."""
+        out = StringIO()
+        self.write_bytecode(out)
+        return out.getvalue()
+
+
+class BytecodeCache(object):
+    """To implement your own bytecode cache you have to subclass this class
+    and override :meth:`load_bytecode` and :meth:`dump_bytecode`.  Both of
+    these methods are passed a :class:`~ambari_jinja2.bccache.Bucket`.
+
+    A very basic bytecode cache that saves the bytecode on the file system::
+
+        from os import path
+
+        class MyCache(BytecodeCache):
+
+            def __init__(self, directory):
+                self.directory = directory
+
+            def load_bytecode(self, bucket):
+                filename = path.join(self.directory, bucket.key)
+                if path.exists(filename):
+                    with open(filename, 'rb') as f:
+                        bucket.load_bytecode(f)
+
+            def dump_bytecode(self, bucket):
+                filename = path.join(self.directory, bucket.key)
+                with open(filename, 'wb') as f:
+                    bucket.write_bytecode(f)
+
+    A more advanced version of a filesystem based bytecode cache is part of
+    Jinja2.
+    """
+
+    def load_bytecode(self, bucket):
+        """Subclasses have to override this method to load bytecode into a
+        bucket.  If they are not able to find code in the cache for the
+        bucket, it must not do anything.
+        """
+        raise NotImplementedError()
+
+    def dump_bytecode(self, bucket):
+        """Subclasses have to override this method to write the bytecode
+        from a bucket back to the cache.  If it unable to do so it must not
+        fail silently but raise an exception.
+        """
+        raise NotImplementedError()
+
+    def clear(self):
+        """Clears the cache.  This method is not used by Jinja2 but should be
+        implemented to allow applications to clear the bytecode cache used
+        by a particular environment.
+        """
+
+    def get_cache_key(self, name, filename=None):
+        """Returns the unique hash key for this template name."""
+        hash = sha1(name.encode('utf-8'))
+        if filename is not None:
+            if isinstance(filename, unicode):
+                filename = filename.encode('utf-8')
+            hash.update('|' + filename)
+        return hash.hexdigest()
+
+    def get_source_checksum(self, source):
+        """Returns a checksum for the source."""
+        return sha1(source.encode('utf-8')).hexdigest()
+
+    def get_bucket(self, environment, name, filename, source):
+        """Return a cache bucket for the given template.  All arguments are
+        mandatory but filename may be `None`.
+        """
+        key = self.get_cache_key(name, filename)
+        checksum = self.get_source_checksum(source)
+        bucket = Bucket(environment, key, checksum)
+        self.load_bytecode(bucket)
+        return bucket
+
+    def set_bucket(self, bucket):
+        """Put the bucket into the cache."""
+        self.dump_bytecode(bucket)
+
+
+class FileSystemBytecodeCache(BytecodeCache):
+    """A bytecode cache that stores bytecode on the filesystem.  It accepts
+    two arguments: The directory where the cache items are stored and a
+    pattern string that is used to build the filename.
+
+    If no directory is specified the system temporary items folder is used.
+
+    The pattern can be used to have multiple separate caches operate on the
+    same directory.  The default pattern is ``'__ambari_jinja2_%s.cache'``.  ``%s``
+    is replaced with the cache key.
+
+    >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
+
+    This bytecode cache supports clearing of the cache using the clear method.
+    """
+
+    def __init__(self, directory=None, pattern='__ambari_jinja2_%s.cache'):
+        if directory is None:
+            directory = tempfile.gettempdir()
+        self.directory = directory
+        self.pattern = pattern
+
+    def _get_cache_filename(self, bucket):
+        return path.join(self.directory, self.pattern % bucket.key)
+
+    def load_bytecode(self, bucket):
+        f = open_if_exists(self._get_cache_filename(bucket), 'rb')
+        if f is not None:
+            try:
+                bucket.load_bytecode(f)
+            finally:
+                f.close()
+
+    def dump_bytecode(self, bucket):
+        f = open(self._get_cache_filename(bucket), 'wb')
+        try:
+            bucket.write_bytecode(f)
+        finally:
+            f.close()
+
+    def clear(self):
+        # imported lazily here because google app-engine doesn't support
+        # write access on the file system and the function does not exist
+        # normally.
+        from os import remove
+        files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
+        for filename in files:
+            try:
+                remove(path.join(self.directory, filename))
+            except OSError:
+                pass
+
+
+class MemcachedBytecodeCache(BytecodeCache):
+    """This class implements a bytecode cache that uses a memcache cache for
+    storing the information.  It does not enforce a specific memcache library
+    (tummy's memcache or cmemcache) but will accept any class that provides
+    the minimal interface required.
+
+    Libraries compatible with this class:
+
+    -   `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
+    -   `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
+    -   `cmemcache <http://gijsbert.org/cmemcache/>`_
+
+    (Unfortunately the django cache interface is not compatible because it
+    does not support storing binary data, only unicode.  You can however pass
+    the underlying cache client to the bytecode cache which is available
+    as `django.core.cache.cache._client`.)
+
+    The minimal interface for the client passed to the constructor is this:
+
+    .. class:: MinimalClientInterface
+
+        .. method:: set(key, value[, timeout])
+
+            Stores the bytecode in the cache.  `value` is a string and
+            `timeout` the timeout of the key.  If timeout is not provided
+            a default timeout or no timeout should be assumed, if it's
+            provided it's an integer with the number of seconds the cache
+            item should exist.
+
+        .. method:: get(key)
+
+            Returns the value for the cache key.  If the item does not
+            exist in the cache the return value must be `None`.
+
+    The other arguments to the constructor are the prefix for all keys that
+    is added before the actual cache key and the timeout for the bytecode in
+    the cache system.  We recommend a high (or no) timeout.
+
+    This bytecode cache does not support clearing of used items in the cache.
+    The clear method is a no-operation function.
+    """
+
+    def __init__(self, client, prefix='ambari_jinja2/bytecode/', timeout=None):
+        self.client = client
+        self.prefix = prefix
+        self.timeout = timeout
+
+    def load_bytecode(self, bucket):
+        code = self.client.get(self.prefix + bucket.key)
+        if code is not None:
+            bucket.bytecode_from_string(code)
+
+    def dump_bytecode(self, bucket):
+        args = (self.prefix + bucket.key, bucket.bytecode_to_string())
+        if self.timeout is not None:
+            args += (self.timeout,)
+        self.client.set(*args)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py
new file mode 100644
index 0000000..f7a52f4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py
@@ -0,0 +1,1640 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.compiler
+    ~~~~~~~~~~~~~~~
+
+    Compiles nodes into python code.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from cStringIO import StringIO
+from itertools import chain
+from copy import deepcopy
+from ambari_jinja2 import nodes
+from ambari_jinja2.nodes import EvalContext
+from ambari_jinja2.visitor import NodeVisitor, NodeTransformer
+from ambari_jinja2.exceptions import TemplateAssertionError
+from ambari_jinja2.utils import Markup, concat, escape, is_python_keyword, next
+
+
+operators = {
+    'eq':       '==',
+    'ne':       '!=',
+    'gt':       '>',
+    'gteq':     '>=',
+    'lt':       '<',
+    'lteq':     '<=',
+    'in':       'in',
+    'notin':    'not in'
+}
+
+try:
+    exec '(0 if 0 else 0)'
+except SyntaxError:
+    have_condexpr = False
+else:
+    have_condexpr = True
+
+
+# what method to iterate over items do we want to use for dict iteration
+# in generated code?  on 2.x let's go with iteritems, on 3.x with items
+if hasattr(dict, 'iteritems'):
+    dict_item_iter = 'iteritems'
+else:
+    dict_item_iter = 'items'
+
+
+# does if 0: dummy(x) get us x into the scope?
+def unoptimize_before_dead_code():
+    x = 42
+    def f():
+        if 0: dummy(x)
+    return f
+unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
+
+
+def generate(node, environment, name, filename, stream=None,
+             defer_init=False):
+    """Generate the python source for a node tree."""
+    if not isinstance(node, nodes.Template):
+        raise TypeError('Can\'t compile non template nodes')
+    generator = CodeGenerator(environment, name, filename, stream, defer_init)
+    generator.visit(node)
+    if stream is None:
+        return generator.stream.getvalue()
+
+
+def has_safe_repr(value):
+    """Does the node have a safe representation?"""
+    if value is None or value is NotImplemented or value is Ellipsis:
+        return True
+    if isinstance(value, (bool, int, long, float, complex, basestring,
+                          xrange, Markup)):
+        return True
+    if isinstance(value, (tuple, list, set, frozenset)):
+        for item in value:
+            if not has_safe_repr(item):
+                return False
+        return True
+    elif isinstance(value, dict):
+        for key, value in value.iteritems():
+            if not has_safe_repr(key):
+                return False
+            if not has_safe_repr(value):
+                return False
+        return True
+    return False
+
+
+def find_undeclared(nodes, names):
+    """Check if the names passed are accessed undeclared.  The return value
+    is a set of all the undeclared names from the sequence of names found.
+    """
+    visitor = UndeclaredNameVisitor(names)
+    try:
+        for node in nodes:
+            visitor.visit(node)
+    except VisitorExit:
+        pass
+    return visitor.undeclared
+
+
+class Identifiers(object):
+    """Tracks the status of identifiers in frames."""
+
+    def __init__(self):
+        # variables that are known to be declared (probably from outer
+        # frames or because they are special for the frame)
+        self.declared = set()
+
+        # undeclared variables from outer scopes
+        self.outer_undeclared = set()
+
+        # names that are accessed without being explicitly declared by
+        # this one or any of the outer scopes.  Names can appear both in
+        # declared and undeclared.
+        self.undeclared = set()
+
+        # names that are declared locally
+        self.declared_locally = set()
+
+        # names that are declared by parameters
+        self.declared_parameter = set()
+
+    def add_special(self, name):
+        """Register a special name like `loop`."""
+        self.undeclared.discard(name)
+        self.declared.add(name)
+
+    def is_declared(self, name, local_only=False):
+        """Check if a name is declared in this or an outer scope."""
+        if name in self.declared_locally or name in self.declared_parameter:
+            return True
+        if local_only:
+            return False
+        return name in self.declared
+
+    def copy(self):
+        return deepcopy(self)
+
+
+class Frame(object):
+    """Holds compile time information for us."""
+
+    def __init__(self, eval_ctx, parent=None):
+        self.eval_ctx = eval_ctx
+        self.identifiers = Identifiers()
+
+        # a toplevel frame is the root + soft frames such as if conditions.
+        self.toplevel = False
+
+        # the root frame is basically just the outermost frame, so no if
+        # conditions.  This information is used to optimize inheritance
+        # situations.
+        self.rootlevel = False
+
+        # in some dynamic inheritance situations the compiler needs to add
+        # write tests around output statements.
+        self.require_output_check = parent and parent.require_output_check
+
+        # inside some tags we are using a buffer rather than yield statements.
+        # this for example affects {% filter %} or {% macro %}.  If a frame
+        # is buffered this variable points to the name of the list used as
+        # buffer.
+        self.buffer = None
+
+        # the name of the block we're in, otherwise None.
+        self.block = parent and parent.block or None
+
+        # a set of actually assigned names
+        self.assigned_names = set()
+
+        # the parent of this frame
+        self.parent = parent
+
+        if parent is not None:
+            self.identifiers.declared.update(
+                parent.identifiers.declared |
+                parent.identifiers.declared_parameter |
+                parent.assigned_names
+            )
+            self.identifiers.outer_undeclared.update(
+                parent.identifiers.undeclared -
+                self.identifiers.declared
+            )
+            self.buffer = parent.buffer
+
+    def copy(self):
+        """Create a copy of the current one."""
+        rv = object.__new__(self.__class__)
+        rv.__dict__.update(self.__dict__)
+        rv.identifiers = object.__new__(self.identifiers.__class__)
+        rv.identifiers.__dict__.update(self.identifiers.__dict__)
+        return rv
+
+    def inspect(self, nodes, hard_scope=False):
+        """Walk the node and check for identifiers.  If the scope is hard (eg:
+        enforce on a python level) overrides from outer scopes are tracked
+        differently.
+        """
+        visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
+        for node in nodes:
+            visitor.visit(node)
+
+    def find_shadowed(self, extra=()):
+        """Find all the shadowed names.  extra is an iterable of variables
+        that may be defined with `add_special` which may occour scoped.
+        """
+        i = self.identifiers
+        return (i.declared | i.outer_undeclared) & \
+               (i.declared_locally | i.declared_parameter) | \
+               set(x for x in extra if i.is_declared(x))
+
+    def inner(self):
+        """Return an inner frame."""
+        return Frame(self.eval_ctx, self)
+
+    def soft(self):
+        """Return a soft frame.  A soft frame may not be modified as
+        standalone thing as it shares the resources with the frame it
+        was created of, but it's not a rootlevel frame any longer.
+        """
+        rv = self.copy()
+        rv.rootlevel = False
+        return rv
+
+    __copy__ = copy
+
+
+class VisitorExit(RuntimeError):
+    """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
+
+
+class DependencyFinderVisitor(NodeVisitor):
+    """A visitor that collects filter and test calls."""
+
+    def __init__(self):
+        self.filters = set()
+        self.tests = set()
+
+    def visit_Filter(self, node):
+        self.generic_visit(node)
+        self.filters.add(node.name)
+
+    def visit_Test(self, node):
+        self.generic_visit(node)
+        self.tests.add(node.name)
+
+    def visit_Block(self, node):
+        """Stop visiting at blocks."""
+
+
+class UndeclaredNameVisitor(NodeVisitor):
+    """A visitor that checks if a name is accessed without being
+    declared.  This is different from the frame visitor as it will
+    not stop at closure frames.
+    """
+
+    def __init__(self, names):
+        self.names = set(names)
+        self.undeclared = set()
+
+    def visit_Name(self, node):
+        if node.ctx == 'load' and node.name in self.names:
+            self.undeclared.add(node.name)
+            if self.undeclared == self.names:
+                raise VisitorExit()
+        else:
+            self.names.discard(node.name)
+
+    def visit_Block(self, node):
+        """Stop visiting a blocks."""
+
+
+class FrameIdentifierVisitor(NodeVisitor):
+    """A visitor for `Frame.inspect`."""
+
+    def __init__(self, identifiers, hard_scope):
+        self.identifiers = identifiers
+        self.hard_scope = hard_scope
+
+    def visit_Name(self, node):
+        """All assignments to names go through this function."""
+        if node.ctx == 'store':
+            self.identifiers.declared_locally.add(node.name)
+        elif node.ctx == 'param':
+            self.identifiers.declared_parameter.add(node.name)
+        elif node.ctx == 'load' and not \
+             self.identifiers.is_declared(node.name, self.hard_scope):
+            self.identifiers.undeclared.add(node.name)
+
+    def visit_If(self, node):
+        self.visit(node.test)
+        real_identifiers = self.identifiers
+
+        old_names = real_identifiers.declared_locally | \
+                    real_identifiers.declared_parameter
+
+        def inner_visit(nodes):
+            if not nodes:
+                return set()
+            self.identifiers = real_identifiers.copy()
+            for subnode in nodes:
+                self.visit(subnode)
+            rv = self.identifiers.declared_locally - old_names
+            # we have to remember the undeclared variables of this branch
+            # because we will have to pull them.
+            real_identifiers.undeclared.update(self.identifiers.undeclared)
+            self.identifiers = real_identifiers
+            return rv
+
+        body = inner_visit(node.body)
+        else_ = inner_visit(node.else_ or ())
+
+        # the differences between the two branches are also pulled as
+        # undeclared variables
+        real_identifiers.undeclared.update(body.symmetric_difference(else_) -
+                                           real_identifiers.declared)
+
+        # remember those that are declared.
+        real_identifiers.declared_locally.update(body | else_)
+
+    def visit_Macro(self, node):
+        self.identifiers.declared_locally.add(node.name)
+
+    def visit_Import(self, node):
+        self.generic_visit(node)
+        self.identifiers.declared_locally.add(node.target)
+
+    def visit_FromImport(self, node):
+        self.generic_visit(node)
+        for name in node.names:
+            if isinstance(name, tuple):
+                self.identifiers.declared_locally.add(name[1])
+            else:
+                self.identifiers.declared_locally.add(name)
+
+    def visit_Assign(self, node):
+        """Visit assignments in the correct order."""
+        self.visit(node.node)
+        self.visit(node.target)
+
+    def visit_For(self, node):
+        """Visiting stops at for blocks.  However the block sequence
+        is visited as part of the outer scope.
+        """
+        self.visit(node.iter)
+
+    def visit_CallBlock(self, node):
+        self.visit(node.call)
+
+    def visit_FilterBlock(self, node):
+        self.visit(node.filter)
+
+    def visit_Scope(self, node):
+        """Stop visiting at scopes."""
+
+    def visit_Block(self, node):
+        """Stop visiting at blocks."""
+
+
+class CompilerExit(Exception):
+    """Raised if the compiler encountered a situation where it just
+    doesn't make sense to further process the code.  Any block that
+    raises such an exception is not further processed.
+    """
+
+
+class CodeGenerator(NodeVisitor):
+
+    def __init__(self, environment, name, filename, stream=None,
+                 defer_init=False):
+        if stream is None:
+            stream = StringIO()
+        self.environment = environment
+        self.name = name
+        self.filename = filename
+        self.stream = stream
+        self.created_block_context = False
+        self.defer_init = defer_init
+
+        # aliases for imports
+        self.import_aliases = {}
+
+        # a registry for all blocks.  Because blocks are moved out
+        # into the global python scope they are registered here
+        self.blocks = {}
+
+        # the number of extends statements so far
+        self.extends_so_far = 0
+
+        # some templates have a rootlevel extends.  In this case we
+        # can safely assume that we're a child template and do some
+        # more optimizations.
+        self.has_known_extends = False
+
+        # the current line number
+        self.code_lineno = 1
+
+        # registry of all filters and tests (global, not block local)
+        self.tests = {}
+        self.filters = {}
+
+        # the debug information
+        self.debug_info = []
+        self._write_debug_info = None
+
+        # the number of new lines before the next write()
+        self._new_lines = 0
+
+        # the line number of the last written statement
+        self._last_line = 0
+
+        # true if nothing was written so far.
+        self._first_write = True
+
+        # used by the `temporary_identifier` method to get new
+        # unique, temporary identifier
+        self._last_identifier = 0
+
+        # the current indentation
+        self._indentation = 0
+
+    # -- Various compilation helpers
+
+    def fail(self, msg, lineno):
+        """Fail with a :exc:`TemplateAssertionError`."""
+        raise TemplateAssertionError(msg, lineno, self.name, self.filename)
+
+    def temporary_identifier(self):
+        """Get a new unique identifier."""
+        self._last_identifier += 1
+        return 't_%d' % self._last_identifier
+
+    def buffer(self, frame):
+        """Enable buffering for the frame from that point onwards."""
+        frame.buffer = self.temporary_identifier()
+        self.writeline('%s = []' % frame.buffer)
+
+    def return_buffer_contents(self, frame):
+        """Return the buffer contents of the frame."""
+        if frame.eval_ctx.volatile:
+            self.writeline('if context.eval_ctx.autoescape:')
+            self.indent()
+            self.writeline('return Markup(concat(%s))' % frame.buffer)
+            self.outdent()
+            self.writeline('else:')
+            self.indent()
+            self.writeline('return concat(%s)' % frame.buffer)
+            self.outdent()
+        elif frame.eval_ctx.autoescape:
+            self.writeline('return Markup(concat(%s))' % frame.buffer)
+        else:
+            self.writeline('return concat(%s)' % frame.buffer)
+
+    def indent(self):
+        """Indent by one."""
+        self._indentation += 1
+
+    def outdent(self, step=1):
+        """Outdent by step."""
+        self._indentation -= step
+
+    def start_write(self, frame, node=None):
+        """Yield or write into the frame buffer."""
+        if frame.buffer is None:
+            self.writeline('yield ', node)
+        else:
+            self.writeline('%s.append(' % frame.buffer, node)
+
+    def end_write(self, frame):
+        """End the writing process started by `start_write`."""
+        if frame.buffer is not None:
+            self.write(')')
+
+    def simple_write(self, s, frame, node=None):
+        """Simple shortcut for start_write + write + end_write."""
+        self.start_write(frame, node)
+        self.write(s)
+        self.end_write(frame)
+
+    def blockvisit(self, nodes, frame):
+        """Visit a list of nodes as block in a frame.  If the current frame
+        is no buffer a dummy ``if 0: yield None`` is written automatically
+        unless the force_generator parameter is set to False.
+        """
+        if frame.buffer is None:
+            self.writeline('if 0: yield None')
+        else:
+            self.writeline('pass')
+        try:
+            for node in nodes:
+                self.visit(node, frame)
+        except CompilerExit:
+            pass
+
+    def write(self, x):
+        """Write a string into the output stream."""
+        if self._new_lines:
+            if not self._first_write:
+                self.stream.write('\n' * self._new_lines)
+                self.code_lineno += self._new_lines
+                if self._write_debug_info is not None:
+                    self.debug_info.append((self._write_debug_info,
+                                            self.code_lineno))
+                    self._write_debug_info = None
+            self._first_write = False
+            self.stream.write('    ' * self._indentation)
+            self._new_lines = 0
+        self.stream.write(x)
+
+    def writeline(self, x, node=None, extra=0):
+        """Combination of newline and write."""
+        self.newline(node, extra)
+        self.write(x)
+
+    def newline(self, node=None, extra=0):
+        """Add one or more newlines before the next write."""
+        self._new_lines = max(self._new_lines, 1 + extra)
+        if node is not None and node.lineno != self._last_line:
+            self._write_debug_info = node.lineno
+            self._last_line = node.lineno
+
+    def signature(self, node, frame, extra_kwargs=None):
+        """Writes a function call to the stream for the current node.
+        A leading comma is added automatically.  The extra keyword
+        arguments may not include python keywords otherwise a syntax
+        error could occour.  The extra keyword arguments should be given
+        as python dict.
+        """
+        # if any of the given keyword arguments is a python keyword
+        # we have to make sure that no invalid call is created.
+        kwarg_workaround = False
+        for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
+            if is_python_keyword(kwarg):
+                kwarg_workaround = True
+                break
+
+        for arg in node.args:
+            self.write(', ')
+            self.visit(arg, frame)
+
+        if not kwarg_workaround:
+            for kwarg in node.kwargs:
+                self.write(', ')
+                self.visit(kwarg, frame)
+            if extra_kwargs is not None:
+                for key, value in extra_kwargs.iteritems():
+                    self.write(', %s=%s' % (key, value))
+        if node.dyn_args:
+            self.write(', *')
+            self.visit(node.dyn_args, frame)
+
+        if kwarg_workaround:
+            if node.dyn_kwargs is not None:
+                self.write(', **dict({')
+            else:
+                self.write(', **{')
+            for kwarg in node.kwargs:
+                self.write('%r: ' % kwarg.key)
+                self.visit(kwarg.value, frame)
+                self.write(', ')
+            if extra_kwargs is not None:
+                for key, value in extra_kwargs.iteritems():
+                    self.write('%r: %s, ' % (key, value))
+            if node.dyn_kwargs is not None:
+                self.write('}, **')
+                self.visit(node.dyn_kwargs, frame)
+                self.write(')')
+            else:
+                self.write('}')
+
+        elif node.dyn_kwargs is not None:
+            self.write(', **')
+            self.visit(node.dyn_kwargs, frame)
+
+    def pull_locals(self, frame):
+        """Pull all the references identifiers into the local scope."""
+        for name in frame.identifiers.undeclared:
+            self.writeline('l_%s = context.resolve(%r)' % (name, name))
+
+    def pull_dependencies(self, nodes):
+        """Pull all the dependencies."""
+        visitor = DependencyFinderVisitor()
+        for node in nodes:
+            visitor.visit(node)
+        for dependency in 'filters', 'tests':
+            mapping = getattr(self, dependency)
+            for name in getattr(visitor, dependency):
+                if name not in mapping:
+                    mapping[name] = self.temporary_identifier()
+                self.writeline('%s = environment.%s[%r]' %
+                               (mapping[name], dependency, name))
+
+    def unoptimize_scope(self, frame):
+        """Disable Python optimizations for the frame."""
+        # XXX: this is not that nice but it has no real overhead.  It
+        # mainly works because python finds the locals before dead code
+        # is removed.  If that breaks we have to add a dummy function
+        # that just accepts the arguments and does nothing.
+        if frame.identifiers.declared:
+            self.writeline('%sdummy(%s)' % (
+                unoptimize_before_dead_code and 'if 0: ' or '',
+                ', '.join('l_' + name for name in frame.identifiers.declared)
+            ))
+
+    def push_scope(self, frame, extra_vars=()):
+        """This function returns all the shadowed variables in a dict
+        in the form name: alias and will write the required assignments
+        into the current scope.  No indentation takes place.
+
+        This also predefines locally declared variables from the loop
+        body because under some circumstances it may be the case that
+
+        `extra_vars` is passed to `Frame.find_shadowed`.
+        """
+        aliases = {}
+        for name in frame.find_shadowed(extra_vars):
+            aliases[name] = ident = self.temporary_identifier()
+            self.writeline('%s = l_%s' % (ident, name))
+        to_declare = set()
+        for name in frame.identifiers.declared_locally:
+            if name not in aliases:
+                to_declare.add('l_' + name)
+        if to_declare:
+            self.writeline(' = '.join(to_declare) + ' = missing')
+        return aliases
+
+    def pop_scope(self, aliases, frame):
+        """Restore all aliases and delete unused variables."""
+        for name, alias in aliases.iteritems():
+            self.writeline('l_%s = %s' % (name, alias))
+        to_delete = set()
+        for name in frame.identifiers.declared_locally:
+            if name not in aliases:
+                to_delete.add('l_' + name)
+        if to_delete:
+            # we cannot use the del statement here because enclosed
+            # scopes can trigger a SyntaxError:
+            #   a = 42; b = lambda: a; del a
+            self.writeline(' = '.join(to_delete) + ' = missing')
+
+    def function_scoping(self, node, frame, children=None,
+                         find_special=True):
+        """In Jinja a few statements require the help of anonymous
+        functions.  Those are currently macros and call blocks and in
+        the future also recursive loops.  As there is currently
+        technical limitation that doesn't allow reading and writing a
+        variable in a scope where the initial value is coming from an
+        outer scope, this function tries to fall back with a common
+        error message.  Additionally the frame passed is modified so
+        that the argumetns are collected and callers are looked up.
+
+        This will return the modified frame.
+        """
+        # we have to iterate twice over it, make sure that works
+        if children is None:
+            children = node.iter_child_nodes()
+        children = list(children)
+        func_frame = frame.inner()
+        func_frame.inspect(children, hard_scope=True)
+
+        # variables that are undeclared (accessed before declaration) and
+        # declared locally *and* part of an outside scope raise a template
+        # assertion error. Reason: we can't generate reasonable code from
+        # it without aliasing all the variables.
+        # this could be fixed in Python 3 where we have the nonlocal
+        # keyword or if we switch to bytecode generation
+        overriden_closure_vars = (
+            func_frame.identifiers.undeclared &
+            func_frame.identifiers.declared &
+            (func_frame.identifiers.declared_locally |
+             func_frame.identifiers.declared_parameter)
+        )
+        if overriden_closure_vars:
+            self.fail('It\'s not possible to set and access variables '
+                      'derived from an outer scope! (affects: %s)' %
+                      ', '.join(sorted(overriden_closure_vars)), node.lineno)
+
+        # remove variables from a closure from the frame's undeclared
+        # identifiers.
+        func_frame.identifiers.undeclared -= (
+            func_frame.identifiers.undeclared &
+            func_frame.identifiers.declared
+        )
+
+        # no special variables for this scope, abort early
+        if not find_special:
+            return func_frame
+
+        func_frame.accesses_kwargs = False
+        func_frame.accesses_varargs = False
+        func_frame.accesses_caller = False
+        func_frame.arguments = args = ['l_' + x.name for x in node.args]
+
+        undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
+
+        if 'caller' in undeclared:
+            func_frame.accesses_caller = True
+            func_frame.identifiers.add_special('caller')
+            args.append('l_caller')
+        if 'kwargs' in undeclared:
+            func_frame.accesses_kwargs = True
+            func_frame.identifiers.add_special('kwargs')
+            args.append('l_kwargs')
+        if 'varargs' in undeclared:
+            func_frame.accesses_varargs = True
+            func_frame.identifiers.add_special('varargs')
+            args.append('l_varargs')
+        return func_frame
+
+    def macro_body(self, node, frame, children=None):
+        """Dump the function def of a macro or call block."""
+        frame = self.function_scoping(node, frame, children)
+        # macros are delayed, they never require output checks
+        frame.require_output_check = False
+        args = frame.arguments
+        # XXX: this is an ugly fix for the loop nesting bug
+        # (tests.test_old_bugs.test_loop_call_bug).  This works around
+        # a identifier nesting problem we have in general.  It's just more
+        # likely to happen in loops which is why we work around it.  The
+        # real solution would be "nonlocal" all the identifiers that are
+        # leaking into a new python frame and might be used both unassigned
+        # and assigned.
+        if 'loop' in frame.identifiers.declared:
+            args = args + ['l_loop=l_loop']
+        self.writeline('def macro(%s):' % ', '.join(args), node)
+        self.indent()
+        self.buffer(frame)
+        self.pull_locals(frame)
+        self.blockvisit(node.body, frame)
+        self.return_buffer_contents(frame)
+        self.outdent()
+        return frame
+
+    def macro_def(self, node, frame):
+        """Dump the macro definition for the def created by macro_body."""
+        arg_tuple = ', '.join(repr(x.name) for x in node.args)
+        name = getattr(node, 'name', None)
+        if len(node.args) == 1:
+            arg_tuple += ','
+        self.write('Macro(environment, macro, %r, (%s), (' %
+                   (name, arg_tuple))
+        for arg in node.defaults:
+            self.visit(arg, frame)
+            self.write(', ')
+        self.write('), %r, %r, %r)' % (
+            bool(frame.accesses_kwargs),
+            bool(frame.accesses_varargs),
+            bool(frame.accesses_caller)
+        ))
+
+    def position(self, node):
+        """Return a human readable position for the node."""
+        rv = 'line %d' % node.lineno
+        if self.name is not None:
+            rv += ' in ' + repr(self.name)
+        return rv
+
+    # -- Statement Visitors
+
+    def visit_Template(self, node, frame=None):
+        assert frame is None, 'no root frame allowed'
+        eval_ctx = EvalContext(self.environment, self.name)
+
+        from ambari_jinja2.runtime import __all__ as exported
+        self.writeline('from __future__ import division')
+        self.writeline('from ambari_jinja2.runtime import ' + ', '.join(exported))
+        if not unoptimize_before_dead_code:
+            self.writeline('dummy = lambda *x: None')
+
+        # if we want a deferred initialization we cannot move the
+        # environment into a local name
+        envenv = not self.defer_init and ', environment=environment' or ''
+
+        # do we have an extends tag at all?  If not, we can save some
+        # overhead by just not processing any inheritance code.
+        have_extends = node.find(nodes.Extends) is not None
+
+        # find all blocks
+        for block in node.find_all(nodes.Block):
+            if block.name in self.blocks:
+                self.fail('block %r defined twice' % block.name, block.lineno)
+            self.blocks[block.name] = block
+
+        # find all imports and import them
+        for import_ in node.find_all(nodes.ImportedName):
+            if import_.importname not in self.import_aliases:
+                imp = import_.importname
+                self.import_aliases[imp] = alias = self.temporary_identifier()
+                if '.' in imp:
+                    module, obj = imp.rsplit('.', 1)
+                    self.writeline('from %s import %s as %s' %
+                                   (module, obj, alias))
+                else:
+                    self.writeline('import %s as %s' % (imp, alias))
+
+        # add the load name
+        self.writeline('name = %r' % self.name)
+
+        # generate the root render function.
+        self.writeline('def root(context%s):' % envenv, extra=1)
+
+        # process the root
+        frame = Frame(eval_ctx)
+        frame.inspect(node.body)
+        frame.toplevel = frame.rootlevel = True
+        frame.require_output_check = have_extends and not self.has_known_extends
+        self.indent()
+        if have_extends:
+            self.writeline('parent_template = None')
+        if 'self' in find_undeclared(node.body, ('self',)):
+            frame.identifiers.add_special('self')
+            self.writeline('l_self = TemplateReference(context)')
+        self.pull_locals(frame)
+        self.pull_dependencies(node.body)
+        self.blockvisit(node.body, frame)
+        self.outdent()
+
+        # make sure that the parent root is called.
+        if have_extends:
+            if not self.has_known_extends:
+                self.indent()
+                self.writeline('if parent_template is not None:')
+            self.indent()
+            self.writeline('for event in parent_template.'
+                           'root_render_func(context):')
+            self.indent()
+            self.writeline('yield event')
+            self.outdent(2 + (not self.has_known_extends))
+
+        # at this point we now have the blocks collected and can visit them too.
+        for name, block in self.blocks.iteritems():
+            block_frame = Frame(eval_ctx)
+            block_frame.inspect(block.body)
+            block_frame.block = name
+            self.writeline('def block_%s(context%s):' % (name, envenv),
+                           block, 1)
+            self.indent()
+            undeclared = find_undeclared(block.body, ('self', 'super'))
+            if 'self' in undeclared:
+                block_frame.identifiers.add_special('self')
+                self.writeline('l_self = TemplateReference(context)')
+            if 'super' in undeclared:
+                block_frame.identifiers.add_special('super')
+                self.writeline('l_super = context.super(%r, '
+                               'block_%s)' % (name, name))
+            self.pull_locals(block_frame)
+            self.pull_dependencies(block.body)
+            self.blockvisit(block.body, block_frame)
+            self.outdent()
+
+        self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
+                                                   for x in self.blocks),
+                       extra=1)
+
+        # add a function that returns the debug info
+        self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
+                                                    in self.debug_info))
+
+    def visit_Block(self, node, frame):
+        """Call a block and register it for the template."""
+        level = 1
+        if frame.toplevel:
+            # if we know that we are a child template, there is no need to
+            # check if we are one
+            if self.has_known_extends:
+                return
+            if self.extends_so_far > 0:
+                self.writeline('if parent_template is None:')
+                self.indent()
+                level += 1
+        context = node.scoped and 'context.derived(locals())' or 'context'
+        self.writeline('for event in context.blocks[%r][0](%s):' % (
+                       node.name, context), node)
+        self.indent()
+        self.simple_write('event', frame)
+        self.outdent(level)
+
+    def visit_Extends(self, node, frame):
+        """Calls the extender."""
+        if not frame.toplevel:
+            self.fail('cannot use extend from a non top-level scope',
+                      node.lineno)
+
+        # if the number of extends statements in general is zero so
+        # far, we don't have to add a check if something extended
+        # the template before this one.
+        if self.extends_so_far > 0:
+
+            # if we have a known extends we just add a template runtime
+            # error into the generated code.  We could catch that at compile
+            # time too, but i welcome it not to confuse users by throwing the
+            # same error at different times just "because we can".
+            if not self.has_known_extends:
+                self.writeline('if parent_template is not None:')
+                self.indent()
+            self.writeline('raise TemplateRuntimeError(%r)' %
+                           'extended multiple times')
+            self.outdent()
+
+            # if we have a known extends already we don't need that code here
+            # as we know that the template execution will end here.
+            if self.has_known_extends:
+                raise CompilerExit()
+
+        self.writeline('parent_template = environment.get_template(', node)
+        self.visit(node.template, frame)
+        self.write(', %r)' % self.name)
+        self.writeline('for name, parent_block in parent_template.'
+                       'blocks.%s():' % dict_item_iter)
+        self.indent()
+        self.writeline('context.blocks.setdefault(name, []).'
+                       'append(parent_block)')
+        self.outdent()
+
+        # if this extends statement was in the root level we can take
+        # advantage of that information and simplify the generated code
+        # in the top level from this point onwards
+        if frame.rootlevel:
+            self.has_known_extends = True
+
+        # and now we have one more
+        self.extends_so_far += 1
+
+    def visit_Include(self, node, frame):
+        """Handles includes."""
+        if node.with_context:
+            self.unoptimize_scope(frame)
+        if node.ignore_missing:
+            self.writeline('try:')
+            self.indent()
+
+        func_name = 'get_or_select_template'
+        if isinstance(node.template, nodes.Const):
+            if isinstance(node.template.value, basestring):
+                func_name = 'get_template'
+            elif isinstance(node.template.value, (tuple, list)):
+                func_name = 'select_template'
+        elif isinstance(node.template, (nodes.Tuple, nodes.List)):
+            func_name = 'select_template'
+
+        self.writeline('template = environment.%s(' % func_name, node)
+        self.visit(node.template, frame)
+        self.write(', %r)' % self.name)
+        if node.ignore_missing:
+            self.outdent()
+            self.writeline('except TemplateNotFound:')
+            self.indent()
+            self.writeline('pass')
+            self.outdent()
+            self.writeline('else:')
+            self.indent()
+
+        if node.with_context:
+            self.writeline('for event in template.root_render_func('
+                           'template.new_context(context.parent, True, '
+                           'locals())):')
+        else:
+            self.writeline('for event in template.module._body_stream:')
+
+        self.indent()
+        self.simple_write('event', frame)
+        self.outdent()
+
+        if node.ignore_missing:
+            self.outdent()
+
+    def visit_Import(self, node, frame):
+        """Visit regular imports."""
+        if node.with_context:
+            self.unoptimize_scope(frame)
+        self.writeline('l_%s = ' % node.target, node)
+        if frame.toplevel:
+            self.write('context.vars[%r] = ' % node.target)
+        self.write('environment.get_template(')
+        self.visit(node.template, frame)
+        self.write(', %r).' % self.name)
+        if node.with_context:
+            self.write('make_module(context.parent, True, locals())')
+        else:
+            self.write('module')
+        if frame.toplevel and not node.target.startswith('_'):
+            self.writeline('context.exported_vars.discard(%r)' % node.target)
+        frame.assigned_names.add(node.target)
+
+    def visit_FromImport(self, node, frame):
+        """Visit named imports."""
+        self.newline(node)
+        self.write('included_template = environment.get_template(')
+        self.visit(node.template, frame)
+        self.write(', %r).' % self.name)
+        if node.with_context:
+            self.write('make_module(context.parent, True)')
+        else:
+            self.write('module')
+
+        var_names = []
+        discarded_names = []
+        for name in node.names:
+            if isinstance(name, tuple):
+                name, alias = name
+            else:
+                alias = name
+            self.writeline('l_%s = getattr(included_template, '
+                           '%r, missing)' % (alias, name))
+            self.writeline('if l_%s is missing:' % alias)
+            self.indent()
+            self.writeline('l_%s = environment.undefined(%r %% '
+                           'included_template.__name__, '
+                           'name=%r)' %
+                           (alias, 'the template %%r (imported on %s) does '
+                           'not export the requested name %s' % (
+                                self.position(node),
+                                repr(name)
+                           ), name))
+            self.outdent()
+            if frame.toplevel:
+                var_names.append(alias)
+                if not alias.startswith('_'):
+                    discarded_names.append(alias)
+            frame.assigned_names.add(alias)
+
+        if var_names:
+            if len(var_names) == 1:
+                name = var_names[0]
+                self.writeline('context.vars[%r] = l_%s' % (name, name))
+            else:
+                self.writeline('context.vars.update({%s})' % ', '.join(
+                    '%r: l_%s' % (name, name) for name in var_names
+                ))
+        if discarded_names:
+            if len(discarded_names) == 1:
+                self.writeline('context.exported_vars.discard(%r)' %
+                               discarded_names[0])
+            else:
+                self.writeline('context.exported_vars.difference_'
+                               'update((%s))' % ', '.join(map(repr, discarded_names)))
+
+    def visit_For(self, node, frame):
+        # when calculating the nodes for the inner frame we have to exclude
+        # the iterator contents from it
+        children = node.iter_child_nodes(exclude=('iter',))
+        if node.recursive:
+            loop_frame = self.function_scoping(node, frame, children,
+                                               find_special=False)
+        else:
+            loop_frame = frame.inner()
+            loop_frame.inspect(children)
+
+        # try to figure out if we have an extended loop.  An extended loop
+        # is necessary if the loop is in recursive mode if the special loop
+        # variable is accessed in the body.
+        extended_loop = node.recursive or 'loop' in \
+                        find_undeclared(node.iter_child_nodes(
+                            only=('body',)), ('loop',))
+
+        # if we don't have an recursive loop we have to find the shadowed
+        # variables at that point.  Because loops can be nested but the loop
+        # variable is a special one we have to enforce aliasing for it.
+        if not node.recursive:
+            aliases = self.push_scope(loop_frame, ('loop',))
+
+        # otherwise we set up a buffer and add a function def
+        else:
+            self.writeline('def loop(reciter, loop_render_func):', node)
+            self.indent()
+            self.buffer(loop_frame)
+            aliases = {}
+
+        # make sure the loop variable is a special one and raise a template
+        # assertion error if a loop tries to write to loop
+        if extended_loop:
+            loop_frame.identifiers.add_special('loop')
+        for name in node.find_all(nodes.Name):
+            if name.ctx == 'store' and name.name == 'loop':
+                self.fail('Can\'t assign to special loop variable '
+                          'in for-loop target', name.lineno)
+
+        self.pull_locals(loop_frame)
+        if node.else_:
+            iteration_indicator = self.temporary_identifier()
+            self.writeline('%s = 1' % iteration_indicator)
+
+        # Create a fake parent loop if the else or test section of a
+        # loop is accessing the special loop variable and no parent loop
+        # exists.
+        if 'loop' not in aliases and 'loop' in find_undeclared(
+           node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
+            self.writeline("l_loop = environment.undefined(%r, name='loop')" %
+                ("'loop' is undefined. the filter section of a loop as well "
+                 "as the else block doesn't have access to the special 'loop'"
+                 " variable of the current loop.  Because there is no parent "
+                 "loop it's undefined.  Happened in loop on %s" %
+                 self.position(node)))
+
+        self.writeline('for ', node)
+        self.visit(node.target, loop_frame)
+        self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
+
+        # if we have an extened loop and a node test, we filter in the
+        # "outer frame".
+        if extended_loop and node.test is not None:
+            self.write('(')
+            self.visit(node.target, loop_frame)
+            self.write(' for ')
+            self.visit(node.target, loop_frame)
+            self.write(' in ')
+            if node.recursive:
+                self.write('reciter')
+            else:
+                self.visit(node.iter, loop_frame)
+            self.write(' if (')
+            test_frame = loop_frame.copy()
+            self.visit(node.test, test_frame)
+            self.write('))')
+
+        elif node.recursive:
+            self.write('reciter')
+        else:
+            self.visit(node.iter, loop_frame)
+
+        if node.recursive:
+            self.write(', recurse=loop_render_func):')
+        else:
+            self.write(extended_loop and '):' or ':')
+
+        # tests in not extended loops become a continue
+        if not extended_loop and node.test is not None:
+            self.indent()
+            self.writeline('if not ')
+            self.visit(node.test, loop_frame)
+            self.write(':')
+            self.indent()
+            self.writeline('continue')
+            self.outdent(2)
+
+        self.indent()
+        self.blockvisit(node.body, loop_frame)
+        if node.else_:
+            self.writeline('%s = 0' % iteration_indicator)
+        self.outdent()
+
+        if node.else_:
+            self.writeline('if %s:' % iteration_indicator)
+            self.indent()
+            self.blockvisit(node.else_, loop_frame)
+            self.outdent()
+
+        # reset the aliases if there are any.
+        if not node.recursive:
+            self.pop_scope(aliases, loop_frame)
+
+        # if the node was recursive we have to return the buffer contents
+        # and start the iteration code
+        if node.recursive:
+            self.return_buffer_contents(loop_frame)
+            self.outdent()
+            self.start_write(frame, node)
+            self.write('loop(')
+            self.visit(node.iter, frame)
+            self.write(', loop)')
+            self.end_write(frame)
+
+    def visit_If(self, node, frame):
+        if_frame = frame.soft()
+        self.writeline('if ', node)
+        self.visit(node.test, if_frame)
+        self.write(':')
+        self.indent()
+        self.blockvisit(node.body, if_frame)
+        self.outdent()
+        if node.else_:
+            self.writeline('else:')
+            self.indent()
+            self.blockvisit(node.else_, if_frame)
+            self.outdent()
+
+    def visit_Macro(self, node, frame):
+        macro_frame = self.macro_body(node, frame)
+        self.newline()
+        if frame.toplevel:
+            if not node.name.startswith('_'):
+                self.write('context.exported_vars.add(%r)' % node.name)
+            self.writeline('context.vars[%r] = ' % node.name)
+        self.write('l_%s = ' % node.name)
+        self.macro_def(node, macro_frame)
+        frame.assigned_names.add(node.name)
+
+    def visit_CallBlock(self, node, frame):
+        children = node.iter_child_nodes(exclude=('call',))
+        call_frame = self.macro_body(node, frame, children)
+        self.writeline('caller = ')
+        self.macro_def(node, call_frame)
+        self.start_write(frame, node)
+        self.visit_Call(node.call, call_frame, forward_caller=True)
+        self.end_write(frame)
+
+    def visit_FilterBlock(self, node, frame):
+        filter_frame = frame.inner()
+        filter_frame.inspect(node.iter_child_nodes())
+        aliases = self.push_scope(filter_frame)
+        self.pull_locals(filter_frame)
+        self.buffer(filter_frame)
+        self.blockvisit(node.body, filter_frame)
+        self.start_write(frame, node)
+        self.visit_Filter(node.filter, filter_frame)
+        self.end_write(frame)
+        self.pop_scope(aliases, filter_frame)
+
+    def visit_ExprStmt(self, node, frame):
+        self.newline(node)
+        self.visit(node.node, frame)
+
+    def visit_Output(self, node, frame):
+        # if we have a known extends statement, we don't output anything
+        # if we are in a require_output_check section
+        if self.has_known_extends and frame.require_output_check:
+            return
+
+        if self.environment.finalize:
+            finalize = lambda x: unicode(self.environment.finalize(x))
+        else:
+            finalize = unicode
+
+        # if we are inside a frame that requires output checking, we do so
+        outdent_later = False
+        if frame.require_output_check:
+            self.writeline('if parent_template is None:')
+            self.indent()
+            outdent_later = True
+
+        # try to evaluate as many chunks as possible into a static
+        # string at compile time.
+        body = []
+        for child in node.nodes:
+            try:
+                const = child.as_const(frame.eval_ctx)
+            except nodes.Impossible:
+                body.append(child)
+                continue
+            # the frame can't be volatile here, becaus otherwise the
+            # as_const() function would raise an Impossible exception
+            # at that point.
+            try:
+                if frame.eval_ctx.autoescape:
+                    if hasattr(const, '__html__'):
+                        const = const.__html__()
+                    else:
+                        const = escape(const)
+                const = finalize(const)
+            except:
+                # if something goes wrong here we evaluate the node
+                # at runtime for easier debugging
+                body.append(child)
+                continue
+            if body and isinstance(body[-1], list):
+                body[-1].append(const)
+            else:
+                body.append([const])
+
+        # if we have less than 3 nodes or a buffer we yield or extend/append
+        if len(body) < 3 or frame.buffer is not None:
+            if frame.buffer is not None:
+                # for one item we append, for more we extend
+                if len(body) == 1:
+                    self.writeline('%s.append(' % frame.buffer)
+                else:
+                    self.writeline('%s.extend((' % frame.buffer)
+                self.indent()
+            for item in body:
+                if isinstance(item, list):
+                    val = repr(concat(item))
+                    if frame.buffer is None:
+                        self.writeline('yield ' + val)
+                    else:
+                        self.writeline(val + ', ')
+                else:
+                    if frame.buffer is None:
+                        self.writeline('yield ', item)
+                    else:
+                        self.newline(item)
+                    close = 1
+                    if frame.eval_ctx.volatile:
+                        self.write('(context.eval_ctx.autoescape and'
+                                   ' escape or to_string)(')
+                    elif frame.eval_ctx.autoescape:
+                        self.write('escape(')
+                    else:
+                        self.write('to_string(')
+                    if self.environment.finalize is not None:
+                        self.write('environment.finalize(')
+                        close += 1
+                    self.visit(item, frame)
+                    self.write(')' * close)
+                    if frame.buffer is not None:
+                        self.write(', ')
+            if frame.buffer is not None:
+                # close the open parentheses
+                self.outdent()
+                self.writeline(len(body) == 1 and ')' or '))')
+
+        # otherwise we create a format string as this is faster in that case
+        else:
+            format = []
+            arguments = []
+            for item in body:
+                if isinstance(item, list):
+                    format.append(concat(item).replace('%', '%%'))
+                else:
+                    format.append('%s')
+                    arguments.append(item)
+            self.writeline('yield ')
+            self.write(repr(concat(format)) + ' % (')
+            idx = -1
+            self.indent()
+            for argument in arguments:
+                self.newline(argument)
+                close = 0
+                if frame.eval_ctx.volatile:
+                    self.write('(context.eval_ctx.autoescape and'
+                               ' escape or to_string)(')
+                    close += 1
+                elif frame.eval_ctx.autoescape:
+                    self.write('escape(')
+                    close += 1
+                if self.environment.finalize is not None:
+                    self.write('environment.finalize(')
+                    close += 1
+                self.visit(argument, frame)
+                self.write(')' * close + ', ')
+            self.outdent()
+            self.writeline(')')
+
+        if outdent_later:
+            self.outdent()
+
+    def visit_Assign(self, node, frame):
+        self.newline(node)
+        # toplevel assignments however go into the local namespace and
+        # the current template's context.  We create a copy of the frame
+        # here and add a set so that the Name visitor can add the assigned
+        # names here.
+        if frame.toplevel:
+            assignment_frame = frame.copy()
+            assignment_frame.toplevel_assignments = set()
+        else:
+            assignment_frame = frame
+        self.visit(node.target, assignment_frame)
+        self.write(' = ')
+        self.visit(node.node, frame)
+
+        # make sure toplevel assignments are added to the context.
+        if frame.toplevel:
+            public_names = [x for x in assignment_frame.toplevel_assignments
+                            if not x.startswith('_')]
+            if len(assignment_frame.toplevel_assignments) == 1:
+                name = next(iter(assignment_frame.toplevel_assignments))
+                self.writeline('context.vars[%r] = l_%s' % (name, name))
+            else:
+                self.writeline('context.vars.update({')
+                for idx, name in enumerate(assignment_frame.toplevel_assignments):
+                    if idx:
+                        self.write(', ')
+                    self.write('%r: l_%s' % (name, name))
+                self.write('})')
+            if public_names:
+                if len(public_names) == 1:
+                    self.writeline('context.exported_vars.add(%r)' %
+                                   public_names[0])
+                else:
+                    self.writeline('context.exported_vars.update((%s))' %
+                                   ', '.join(map(repr, public_names)))
+
+    # -- Expression Visitors
+
+    def visit_Name(self, node, frame):
+        if node.ctx == 'store' and frame.toplevel:
+            frame.toplevel_assignments.add(node.name)
+        self.write('l_' + node.name)
+        frame.assigned_names.add(node.name)
+
+    def visit_Const(self, node, frame):
+        val = node.value
+        if isinstance(val, float):
+            self.write(str(val))
+        else:
+            self.write(repr(val))
+
+    def visit_TemplateData(self, node, frame):
+        try:
+            self.write(repr(node.as_const(frame.eval_ctx)))
+        except nodes.Impossible:
+            self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
+                       % node.data)
+
+    def visit_Tuple(self, node, frame):
+        self.write('(')
+        idx = -1
+        for idx, item in enumerate(node.items):
+            if idx:
+                self.write(', ')
+            self.visit(item, frame)
+        self.write(idx == 0 and ',)' or ')')
+
+    def visit_List(self, node, frame):
+        self.write('[')
+        for idx, item in enumerate(node.items):
+            if idx:
+                self.write(', ')
+            self.visit(item, frame)
+        self.write(']')
+
+    def visit_Dict(self, node, frame):
+        self.write('{')
+        for idx, item in enumerate(node.items):
+            if idx:
+                self.write(', ')
+            self.visit(item.key, frame)
+            self.write(': ')
+            self.visit(item.value, frame)
+        self.write('}')
+
+    def binop(operator):
+        def visitor(self, node, frame):
+            self.write('(')
+            self.visit(node.left, frame)
+            self.write(' %s ' % operator)
+            self.visit(node.right, frame)
+            self.write(')')
+        return visitor
+
+    def uaop(operator):
+        def visitor(self, node, frame):
+            self.write('(' + operator)
+            self.visit(node.node, frame)
+            self.write(')')
+        return visitor
+
+    visit_Add = binop('+')
+    visit_Sub = binop('-')
+    visit_Mul = binop('*')
+    visit_Div = binop('/')
+    visit_FloorDiv = binop('//')
+    visit_Pow = binop('**')
+    visit_Mod = binop('%')
+    visit_And = binop('and')
+    visit_Or = binop('or')
+    visit_Pos = uaop('+')
+    visit_Neg = uaop('-')
+    visit_Not = uaop('not ')
+    del binop, uaop
+
+    def visit_Concat(self, node, frame):
+        if frame.eval_ctx.volatile:
+            func_name = '(context.eval_ctx.volatile and' \
+                        ' markup_join or unicode_join)'
+        elif frame.eval_ctx.autoescape:
+            func_name = 'markup_join'
+        else:
+            func_name = 'unicode_join'
+        self.write('%s((' % func_name)
+        for arg in node.nodes:
+            self.visit(arg, frame)
+            self.write(', ')
+        self.write('))')
+
+    def visit_Compare(self, node, frame):
+        self.visit(node.expr, frame)
+        for op in node.ops:
+            self.visit(op, frame)
+
+    def visit_Operand(self, node, frame):
+        self.write(' %s ' % operators[node.op])
+        self.visit(node.expr, frame)
+
+    def visit_Getattr(self, node, frame):
+        self.write('environment.getattr(')
+        self.visit(node.node, frame)
+        self.write(', %r)' % node.attr)
+
+    def visit_Getitem(self, node, frame):
+        # slices bypass the environment getitem method.
+        if isinstance(node.arg, nodes.Slice):
+            self.visit(node.node, frame)
+            self.write('[')
+            self.visit(node.arg, frame)
+            self.write(']')
+        else:
+            self.write('environment.getitem(')
+            self.visit(node.node, frame)
+            self.write(', ')
+            self.visit(node.arg, frame)
+            self.write(')')
+
+    def visit_Slice(self, node, frame):
+        if node.start is not None:
+            self.visit(node.start, frame)
+        self.write(':')
+        if node.stop is not None:
+            self.visit(node.stop, frame)
+        if node.step is not None:
+            self.write(':')
+            self.visit(node.step, frame)
+
+    def visit_Filter(self, node, frame):
+        self.write(self.filters[node.name] + '(')
+        func = self.environment.filters.get(node.name)
+        if func is None:
+            self.fail('no filter named %r' % node.name, node.lineno)
+        if getattr(func, 'contextfilter', False):
+            self.write('context, ')
+        elif getattr(func, 'evalcontextfilter', False):
+            self.write('context.eval_ctx, ')
+        elif getattr(func, 'environmentfilter', False):
+            self.write('environment, ')
+
+        # if the filter node is None we are inside a filter block
+        # and want to write to the current buffer
+        if node.node is not None:
+            self.visit(node.node, frame)
+        elif frame.eval_ctx.volatile:
+            self.write('(context.eval_ctx.autoescape and'
+                       ' Markup(concat(%s)) or concat(%s))' %
+                       (frame.buffer, frame.buffer))
+        elif frame.eval_ctx.autoescape:
+            self.write('Markup(concat(%s))' % frame.buffer)
+        else:
+            self.write('concat(%s)' % frame.buffer)
+        self.signature(node, frame)
+        self.write(')')
+
+    def visit_Test(self, node, frame):
+        self.write(self.tests[node.name] + '(')
+        if node.name not in self.environment.tests:
+            self.fail('no test named %r' % node.name, node.lineno)
+        self.visit(node.node, frame)
+        self.signature(node, frame)
+        self.write(')')
+
+    def visit_CondExpr(self, node, frame):
+        def write_expr2():
+            if node.expr2 is not None:
+                return self.visit(node.expr2, frame)
+            self.write('environment.undefined(%r)' % ('the inline if-'
+                       'expression on %s evaluated to false and '
+                       'no else section was defined.' % self.position(node)))
+
+        if not have_condexpr:
+            self.write('((')
+            self.visit(node.test, frame)
+            self.write(') and (')
+            self.visit(node.expr1, frame)
+            self.write(',) or (')
+            write_expr2()
+            self.write(',))[0]')
+        else:
+            self.write('(')
+            self.visit(node.expr1, frame)
+            self.write(' if ')
+            self.visit(node.test, frame)
+            self.write(' else ')
+            write_expr2()
+            self.write(')')
+
+    def visit_Call(self, node, frame, forward_caller=False):
+        if self.environment.sandboxed:
+            self.write('environment.call(context, ')
+        else:
+            self.write('context.call(')
+        self.visit(node.node, frame)
+        extra_kwargs = forward_caller and {'caller': 'caller'} or None
+        self.signature(node, frame, extra_kwargs)
+        self.write(')')
+
+    def visit_Keyword(self, node, frame):
+        self.write(node.key + '=')
+        self.visit(node.value, frame)
+
+    # -- Unused nodes for extensions
+
+    def visit_MarkSafe(self, node, frame):
+        self.write('Markup(')
+        self.visit(node.expr, frame)
+        self.write(')')
+
+    def visit_MarkSafeIfAutoescape(self, node, frame):
+        self.write('(context.eval_ctx.autoescape and Markup or identity)(')
+        self.visit(node.expr, frame)
+        self.write(')')
+
+    def visit_EnvironmentAttribute(self, node, frame):
+        self.write('environment.' + node.name)
+
+    def visit_ExtensionAttribute(self, node, frame):
+        self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
+
+    def visit_ImportedName(self, node, frame):
+        self.write(self.import_aliases[node.importname])
+
+    def visit_InternalName(self, node, frame):
+        self.write(node.name)
+
+    def visit_ContextReference(self, node, frame):
+        self.write('context')
+
+    def visit_Continue(self, node, frame):
+        self.writeline('continue', node)
+
+    def visit_Break(self, node, frame):
+        self.writeline('break', node)
+
+    def visit_Scope(self, node, frame):
+        scope_frame = frame.inner()
+        scope_frame.inspect(node.iter_child_nodes())
+        aliases = self.push_scope(scope_frame)
+        self.pull_locals(scope_frame)
+        self.blockvisit(node.body, scope_frame)
+        self.pop_scope(aliases, scope_frame)
+
+    def visit_EvalContextModifier(self, node, frame):
+        for keyword in node.options:
+            self.writeline('context.eval_ctx.%s = ' % keyword.key)
+            self.visit(keyword.value, frame)
+            try:
+                val = keyword.value.as_const(frame.eval_ctx)
+            except nodes.Impossible:
+                frame.eval_ctx.volatile = True
+            else:
+                setattr(frame.eval_ctx, keyword.key, val)
+
+    def visit_ScopedEvalContextModifier(self, node, frame):
+        old_ctx_name = self.temporary_identifier()
+        safed_ctx = frame.eval_ctx.save()
+        self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
+        self.visit_EvalContextModifier(node, frame)
+        for child in node.body:
+            self.visit(child, frame)
+        frame.eval_ctx.revert(safed_ctx)
+        self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py
new file mode 100644
index 0000000..cab203c
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/constants.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja.constants
+    ~~~~~~~~~~~~~~~
+
+    Various constants.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+
+
+#: list of lorem ipsum words used by the lipsum() helper function
+LOREM_IPSUM_WORDS = u'''\
+a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
+auctor augue bibendum blandit class commodo condimentum congue consectetuer
+consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
+diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
+elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
+faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
+hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
+justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
+luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
+mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
+nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
+penatibus per pharetra phasellus placerat platea porta porttitor posuere
+potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
+ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
+sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
+tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
+ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
+viverra volutpat vulputate'''

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py
new file mode 100644
index 0000000..d48a958
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/debug.py
@@ -0,0 +1,308 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.debug
+    ~~~~~~~~~~~~
+
+    Implements the debug interface for Jinja.  This module does some pretty
+    ugly stuff with the Python traceback system in order to achieve tracebacks
+    with correct line numbers, locals and contents.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import sys
+import traceback
+from ambari_jinja2.utils import CodeType, missing, internal_code
+from ambari_jinja2.exceptions import TemplateSyntaxError
+
+
+# how does the raise helper look like?
+try:
+    exec "raise TypeError, 'foo'"
+except SyntaxError:
+    raise_helper = 'raise __jinja_exception__[1]'
+except TypeError:
+    raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]'
+
+
+class TracebackFrameProxy(object):
+    """Proxies a traceback frame."""
+
+    def __init__(self, tb):
+        self.tb = tb
+
+    def _set_tb_next(self, next):
+        if tb_set_next is not None:
+            tb_set_next(self.tb, next and next.tb or None)
+        self._tb_next = next
+
+    def _get_tb_next(self):
+        return self._tb_next
+
+    tb_next = property(_get_tb_next, _set_tb_next)
+    del _get_tb_next, _set_tb_next
+
+    @property
+    def is_jinja_frame(self):
+        return '__jinja_template__' in self.tb.tb_frame.f_globals
+
+    def __getattr__(self, name):
+        return getattr(self.tb, name)
+
+
+class ProcessedTraceback(object):
+    """Holds a Jinja preprocessed traceback for priting or reraising."""
+
+    def __init__(self, exc_type, exc_value, frames):
+        assert frames, 'no frames for this traceback?'
+        self.exc_type = exc_type
+        self.exc_value = exc_value
+        self.frames = frames
+
+    def chain_frames(self):
+        """Chains the frames.  Requires ctypes or the debugsupport extension."""
+        prev_tb = None
+        for tb in self.frames:
+            if prev_tb is not None:
+                prev_tb.tb_next = tb
+            prev_tb = tb
+        prev_tb.tb_next = None
+
+    def render_as_text(self, limit=None):
+        """Return a string with the traceback."""
+        lines = traceback.format_exception(self.exc_type, self.exc_value,
+                                           self.frames[0], limit=limit)
+        return ''.join(lines).rstrip()
+
+    def render_as_html(self, full=False):
+        """Return a unicode string with the traceback as rendered HTML."""
+        from ambari_jinja2.debugrenderer import render_traceback
+        return u'%s\n\n<!--\n%s\n-->' % (
+            render_traceback(self, full=full),
+            self.render_as_text().decode('utf-8', 'replace')
+        )
+
+    @property
+    def is_template_syntax_error(self):
+        """`True` if this is a template syntax error."""
+        return isinstance(self.exc_value, TemplateSyntaxError)
+
+    @property
+    def exc_info(self):
+        """Exception info tuple with a proxy around the frame objects."""
+        return self.exc_type, self.exc_value, self.frames[0]
+
+    @property
+    def standard_exc_info(self):
+        """Standard python exc_info for re-raising"""
+        return self.exc_type, self.exc_value, self.frames[0].tb
+
+
+def make_traceback(exc_info, source_hint=None):
+    """Creates a processed traceback object from the exc_info."""
+    exc_type, exc_value, tb = exc_info
+    if isinstance(exc_value, TemplateSyntaxError):
+        exc_info = translate_syntax_error(exc_value, source_hint)
+        initial_skip = 0
+    else:
+        initial_skip = 1
+    return translate_exception(exc_info, initial_skip)
+
+
+def translate_syntax_error(error, source=None):
+    """Rewrites a syntax error to please traceback systems."""
+    error.source = source
+    error.translated = True
+    exc_info = (error.__class__, error, None)
+    filename = error.filename
+    if filename is None:
+        filename = '<unknown>'
+    return fake_exc_info(exc_info, filename, error.lineno)
+
+
+def translate_exception(exc_info, initial_skip=0):
+    """If passed an exc_info it will automatically rewrite the exceptions
+    all the way down to the correct line numbers and frames.
+    """
+    tb = exc_info[2]
+    frames = []
+
+    # skip some internal frames if wanted
+    for x in xrange(initial_skip):
+        if tb is not None:
+            tb = tb.tb_next
+    initial_tb = tb
+
+    while tb is not None:
+        # skip frames decorated with @internalcode.  These are internal
+        # calls we can't avoid and that are useless in template debugging
+        # output.
+        if tb.tb_frame.f_code in internal_code:
+            tb = tb.tb_next
+            continue
+
+        # save a reference to the next frame if we override the current
+        # one with a faked one.
+        next = tb.tb_next
+
+        # fake template exceptions
+        template = tb.tb_frame.f_globals.get('__jinja_template__')
+        if template is not None:
+            lineno = template.get_corresponding_lineno(tb.tb_lineno)
+            tb = fake_exc_info(exc_info[:2] + (tb,), template.filename,
+                               lineno)[2]
+
+        frames.append(TracebackFrameProxy(tb))
+        tb = next
+
+    # if we don't have any exceptions in the frames left, we have to
+    # reraise it unchanged.
+    # XXX: can we backup here?  when could this happen?
+    if not frames:
+        raise exc_info[0], exc_info[1], exc_info[2]
+
+    traceback = ProcessedTraceback(exc_info[0], exc_info[1], frames)
+    if tb_set_next is not None:
+        traceback.chain_frames()
+    return traceback
+
+
+def fake_exc_info(exc_info, filename, lineno):
+    """Helper for `translate_exception`."""
+    exc_type, exc_value, tb = exc_info
+
+    # figure the real context out
+    if tb is not None:
+        real_locals = tb.tb_frame.f_locals.copy()
+        ctx = real_locals.get('context')
+        if ctx:
+            locals = ctx.get_all()
+        else:
+            locals = {}
+        for name, value in real_locals.iteritems():
+            if name.startswith('l_') and value is not missing:
+                locals[name[2:]] = value
+
+        # if there is a local called __jinja_exception__, we get
+        # rid of it to not break the debug functionality.
+        locals.pop('__jinja_exception__', None)
+    else:
+        locals = {}
+
+    # assamble fake globals we need
+    globals = {
+        '__name__':             filename,
+        '__file__':             filename,
+        '__jinja_exception__':  exc_info[:2],
+
+        # we don't want to keep the reference to the template around
+        # to not cause circular dependencies, but we mark it as Jinja
+        # frame for the ProcessedTraceback
+        '__jinja_template__':   None
+    }
+
+    # and fake the exception
+    code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec')
+
+    # if it's possible, change the name of the code.  This won't work
+    # on some python environments such as google appengine
+    try:
+        if tb is None:
+            location = 'template'
+        else:
+            function = tb.tb_frame.f_code.co_name
+            if function == 'root':
+                location = 'top-level template code'
+            elif function.startswith('block_'):
+                location = 'block "%s"' % function[6:]
+            else:
+                location = 'template'
+        code = CodeType(0, code.co_nlocals, code.co_stacksize,
+                        code.co_flags, code.co_code, code.co_consts,
+                        code.co_names, code.co_varnames, filename,
+                        location, code.co_firstlineno,
+                        code.co_lnotab, (), ())
+    except:
+        pass
+
+    # execute the code and catch the new traceback
+    try:
+        exec code in globals, locals
+    except:
+        exc_info = sys.exc_info()
+        new_tb = exc_info[2].tb_next
+
+    # return without this frame
+    return exc_info[:2] + (new_tb,)
+
+
+def _init_ugly_crap():
+    """This function implements a few ugly things so that we can patch the
+    traceback objects.  The function returned allows resetting `tb_next` on
+    any python traceback object.
+    """
+    import ctypes
+    from types import TracebackType
+
+    # figure out side of _Py_ssize_t
+    if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
+        _Py_ssize_t = ctypes.c_int64
+    else:
+        _Py_ssize_t = ctypes.c_int
+
+    # regular python
+    class _PyObject(ctypes.Structure):
+        pass
+    _PyObject._fields_ = [
+        ('ob_refcnt', _Py_ssize_t),
+        ('ob_type', ctypes.POINTER(_PyObject))
+    ]
+
+    # python with trace
+    if hasattr(sys, 'getobjects'):
+        class _PyObject(ctypes.Structure):
+            pass
+        _PyObject._fields_ = [
+            ('_ob_next', ctypes.POINTER(_PyObject)),
+            ('_ob_prev', ctypes.POINTER(_PyObject)),
+            ('ob_refcnt', _Py_ssize_t),
+            ('ob_type', ctypes.POINTER(_PyObject))
+        ]
+
+    class _Traceback(_PyObject):
+        pass
+    _Traceback._fields_ = [
+        ('tb_next', ctypes.POINTER(_Traceback)),
+        ('tb_frame', ctypes.POINTER(_PyObject)),
+        ('tb_lasti', ctypes.c_int),
+        ('tb_lineno', ctypes.c_int)
+    ]
+
+    def tb_set_next(tb, next):
+        """Set the tb_next attribute of a traceback object."""
+        if not (isinstance(tb, TracebackType) and
+                (next is None or isinstance(next, TracebackType))):
+            raise TypeError('tb_set_next arguments must be traceback objects')
+        obj = _Traceback.from_address(id(tb))
+        if tb.tb_next is not None:
+            old = _Traceback.from_address(id(tb.tb_next))
+            old.ob_refcnt -= 1
+        if next is None:
+            obj.tb_next = ctypes.POINTER(_Traceback)()
+        else:
+            next = _Traceback.from_address(id(next))
+            next.ob_refcnt += 1
+            obj.tb_next = ctypes.pointer(next)
+
+    return tb_set_next
+
+
+# try to get a tb_set_next implementation
+try:
+    from ambari_jinja2._debugsupport import tb_set_next
+except ImportError:
+    try:
+        tb_set_next = _init_ugly_crap()
+    except:
+        tb_set_next = None
+del _init_ugly_crap

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py
new file mode 100644
index 0000000..566ebca
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/defaults.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.defaults
+    ~~~~~~~~~~~~~~~
+
+    Jinja default filters and tags.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from ambari_jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
+
+
+# defaults for the parser / lexer
+BLOCK_START_STRING = '{%'
+BLOCK_END_STRING = '%}'
+VARIABLE_START_STRING = '{{'
+VARIABLE_END_STRING = '}}'
+COMMENT_START_STRING = '{#'
+COMMENT_END_STRING = '#}'
+LINE_STATEMENT_PREFIX = None
+LINE_COMMENT_PREFIX = None
+TRIM_BLOCKS = False
+NEWLINE_SEQUENCE = '\n'
+
+
+# default filters, tests and namespace
+from ambari_jinja2.filters import FILTERS as DEFAULT_FILTERS
+from ambari_jinja2.tests import TESTS as DEFAULT_TESTS
+DEFAULT_NAMESPACE = {
+    'range':        xrange,
+    'dict':         lambda **kw: kw,
+    'lipsum':       generate_lorem_ipsum,
+    'cycler':       Cycler,
+    'joiner':       Joiner
+}
+
+
+# export all constants
+__all__ = tuple(x for x in locals().keys() if x.isupper())


[03/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/nodes.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/nodes.py b/ambari-common/src/main/python/jinja2/jinja2/nodes.py
new file mode 100644
index 0000000..6446c70
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/nodes.py
@@ -0,0 +1,901 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.nodes
+    ~~~~~~~~~~~~
+
+    This module implements additional nodes derived from the ast base node.
+
+    It also provides some node tree helper functions like `in_lineno` and
+    `get_nodes` used by the parser and translator in order to normalize
+    python and jinja nodes.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import operator
+from itertools import chain, izip
+from collections import deque
+from jinja2.utils import Markup, MethodType, FunctionType
+
+
+#: the types we support for context functions
+_context_function_types = (FunctionType, MethodType)
+
+
+_binop_to_func = {
+    '*':        operator.mul,
+    '/':        operator.truediv,
+    '//':       operator.floordiv,
+    '**':       operator.pow,
+    '%':        operator.mod,
+    '+':        operator.add,
+    '-':        operator.sub
+}
+
+_uaop_to_func = {
+    'not':      operator.not_,
+    '+':        operator.pos,
+    '-':        operator.neg
+}
+
+_cmpop_to_func = {
+    'eq':       operator.eq,
+    'ne':       operator.ne,
+    'gt':       operator.gt,
+    'gteq':     operator.ge,
+    'lt':       operator.lt,
+    'lteq':     operator.le,
+    'in':       lambda a, b: a in b,
+    'notin':    lambda a, b: a not in b
+}
+
+
+class Impossible(Exception):
+    """Raised if the node could not perform a requested action."""
+
+
+class NodeType(type):
+    """A metaclass for nodes that handles the field and attribute
+    inheritance.  fields and attributes from the parent class are
+    automatically forwarded to the child."""
+
+    def __new__(cls, name, bases, d):
+        for attr in 'fields', 'attributes':
+            storage = []
+            storage.extend(getattr(bases[0], attr, ()))
+            storage.extend(d.get(attr, ()))
+            assert len(bases) == 1, 'multiple inheritance not allowed'
+            assert len(storage) == len(set(storage)), 'layout conflict'
+            d[attr] = tuple(storage)
+        d.setdefault('abstract', False)
+        return type.__new__(cls, name, bases, d)
+
+
+class EvalContext(object):
+    """Holds evaluation time information.  Custom attributes can be attached
+    to it in extensions.
+    """
+
+    def __init__(self, environment, template_name=None):
+        if callable(environment.autoescape):
+            self.autoescape = environment.autoescape(template_name)
+        else:
+            self.autoescape = environment.autoescape
+        self.volatile = False
+
+    def save(self):
+        return self.__dict__.copy()
+
+    def revert(self, old):
+        self.__dict__.clear()
+        self.__dict__.update(old)
+
+
+def get_eval_context(node, ctx):
+    if ctx is None:
+        if node.environment is None:
+            raise RuntimeError('if no eval context is passed, the '
+                               'node must have an attached '
+                               'environment.')
+        return EvalContext(node.environment)
+    return ctx
+
+
+class Node(object):
+    """Baseclass for all Jinja2 nodes.  There are a number of nodes available
+    of different types.  There are three major types:
+
+    -   :class:`Stmt`: statements
+    -   :class:`Expr`: expressions
+    -   :class:`Helper`: helper nodes
+    -   :class:`Template`: the outermost wrapper node
+
+    All nodes have fields and attributes.  Fields may be other nodes, lists,
+    or arbitrary values.  Fields are passed to the constructor as regular
+    positional arguments, attributes as keyword arguments.  Each node has
+    two attributes: `lineno` (the line number of the node) and `environment`.
+    The `environment` attribute is set at the end of the parsing process for
+    all nodes automatically.
+    """
+    __metaclass__ = NodeType
+    fields = ()
+    attributes = ('lineno', 'environment')
+    abstract = True
+
+    def __init__(self, *fields, **attributes):
+        if self.abstract:
+            raise TypeError('abstract nodes are not instanciable')
+        if fields:
+            if len(fields) != len(self.fields):
+                if not self.fields:
+                    raise TypeError('%r takes 0 arguments' %
+                                    self.__class__.__name__)
+                raise TypeError('%r takes 0 or %d argument%s' % (
+                    self.__class__.__name__,
+                    len(self.fields),
+                    len(self.fields) != 1 and 's' or ''
+                ))
+            for name, arg in izip(self.fields, fields):
+                setattr(self, name, arg)
+        for attr in self.attributes:
+            setattr(self, attr, attributes.pop(attr, None))
+        if attributes:
+            raise TypeError('unknown attribute %r' %
+                            iter(attributes).next())
+
+    def iter_fields(self, exclude=None, only=None):
+        """This method iterates over all fields that are defined and yields
+        ``(key, value)`` tuples.  Per default all fields are returned, but
+        it's possible to limit that to some fields by providing the `only`
+        parameter or to exclude some using the `exclude` parameter.  Both
+        should be sets or tuples of field names.
+        """
+        for name in self.fields:
+            if (exclude is only is None) or \
+               (exclude is not None and name not in exclude) or \
+               (only is not None and name in only):
+                try:
+                    yield name, getattr(self, name)
+                except AttributeError:
+                    pass
+
+    def iter_child_nodes(self, exclude=None, only=None):
+        """Iterates over all direct child nodes of the node.  This iterates
+        over all fields and yields the values of they are nodes.  If the value
+        of a field is a list all the nodes in that list are returned.
+        """
+        for field, item in self.iter_fields(exclude, only):
+            if isinstance(item, list):
+                for n in item:
+                    if isinstance(n, Node):
+                        yield n
+            elif isinstance(item, Node):
+                yield item
+
+    def find(self, node_type):
+        """Find the first node of a given type.  If no such node exists the
+        return value is `None`.
+        """
+        for result in self.find_all(node_type):
+            return result
+
+    def find_all(self, node_type):
+        """Find all the nodes of a given type.  If the type is a tuple,
+        the check is performed for any of the tuple items.
+        """
+        for child in self.iter_child_nodes():
+            if isinstance(child, node_type):
+                yield child
+            for result in child.find_all(node_type):
+                yield result
+
+    def set_ctx(self, ctx):
+        """Reset the context of a node and all child nodes.  Per default the
+        parser will all generate nodes that have a 'load' context as it's the
+        most common one.  This method is used in the parser to set assignment
+        targets and other nodes to a store context.
+        """
+        todo = deque([self])
+        while todo:
+            node = todo.popleft()
+            if 'ctx' in node.fields:
+                node.ctx = ctx
+            todo.extend(node.iter_child_nodes())
+        return self
+
+    def set_lineno(self, lineno, override=False):
+        """Set the line numbers of the node and children."""
+        todo = deque([self])
+        while todo:
+            node = todo.popleft()
+            if 'lineno' in node.attributes:
+                if node.lineno is None or override:
+                    node.lineno = lineno
+            todo.extend(node.iter_child_nodes())
+        return self
+
+    def set_environment(self, environment):
+        """Set the environment for all nodes."""
+        todo = deque([self])
+        while todo:
+            node = todo.popleft()
+            node.environment = environment
+            todo.extend(node.iter_child_nodes())
+        return self
+
+    def __eq__(self, other):
+        return type(self) is type(other) and \
+               tuple(self.iter_fields()) == tuple(other.iter_fields())
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
+                      arg in self.fields)
+        )
+
+
+class Stmt(Node):
+    """Base node for all statements."""
+    abstract = True
+
+
+class Helper(Node):
+    """Nodes that exist in a specific context only."""
+    abstract = True
+
+
+class Template(Node):
+    """Node that represents a template.  This must be the outermost node that
+    is passed to the compiler.
+    """
+    fields = ('body',)
+
+
+class Output(Stmt):
+    """A node that holds multiple expressions which are then printed out.
+    This is used both for the `print` statement and the regular template data.
+    """
+    fields = ('nodes',)
+
+
+class Extends(Stmt):
+    """Represents an extends statement."""
+    fields = ('template',)
+
+
+class For(Stmt):
+    """The for loop.  `target` is the target for the iteration (usually a
+    :class:`Name` or :class:`Tuple`), `iter` the iterable.  `body` is a list
+    of nodes that are used as loop-body, and `else_` a list of nodes for the
+    `else` block.  If no else node exists it has to be an empty list.
+
+    For filtered nodes an expression can be stored as `test`, otherwise `None`.
+    """
+    fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive')
+
+
+class If(Stmt):
+    """If `test` is true, `body` is rendered, else `else_`."""
+    fields = ('test', 'body', 'else_')
+
+
+class Macro(Stmt):
+    """A macro definition.  `name` is the name of the macro, `args` a list of
+    arguments and `defaults` a list of defaults if there are any.  `body` is
+    a list of nodes for the macro body.
+    """
+    fields = ('name', 'args', 'defaults', 'body')
+
+
+class CallBlock(Stmt):
+    """Like a macro without a name but a call instead.  `call` is called with
+    the unnamed macro as `caller` argument this node holds.
+    """
+    fields = ('call', 'args', 'defaults', 'body')
+
+
+class FilterBlock(Stmt):
+    """Node for filter sections."""
+    fields = ('body', 'filter')
+
+
+class Block(Stmt):
+    """A node that represents a block."""
+    fields = ('name', 'body', 'scoped')
+
+
+class Include(Stmt):
+    """A node that represents the include tag."""
+    fields = ('template', 'with_context', 'ignore_missing')
+
+
+class Import(Stmt):
+    """A node that represents the import tag."""
+    fields = ('template', 'target', 'with_context')
+
+
+class FromImport(Stmt):
+    """A node that represents the from import tag.  It's important to not
+    pass unsafe names to the name attribute.  The compiler translates the
+    attribute lookups directly into getattr calls and does *not* use the
+    subscript callback of the interface.  As exported variables may not
+    start with double underscores (which the parser asserts) this is not a
+    problem for regular Jinja code, but if this node is used in an extension
+    extra care must be taken.
+
+    The list of names may contain tuples if aliases are wanted.
+    """
+    fields = ('template', 'names', 'with_context')
+
+
+class ExprStmt(Stmt):
+    """A statement that evaluates an expression and discards the result."""
+    fields = ('node',)
+
+
+class Assign(Stmt):
+    """Assigns an expression to a target."""
+    fields = ('target', 'node')
+
+
+class Expr(Node):
+    """Baseclass for all expressions."""
+    abstract = True
+
+    def as_const(self, eval_ctx=None):
+        """Return the value of the expression as constant or raise
+        :exc:`Impossible` if this was not possible.
+
+        An :class:`EvalContext` can be provided, if none is given
+        a default context is created which requires the nodes to have
+        an attached environment.
+
+        .. versionchanged:: 2.4
+           the `eval_ctx` parameter was added.
+        """
+        raise Impossible()
+
+    def can_assign(self):
+        """Check if it's possible to assign something to this node."""
+        return False
+
+
+class BinExpr(Expr):
+    """Baseclass for all binary expressions."""
+    fields = ('left', 'right')
+    operator = None
+    abstract = True
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        f = _binop_to_func[self.operator]
+        try:
+            return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx))
+        except:
+            raise Impossible()
+
+
+class UnaryExpr(Expr):
+    """Baseclass for all unary expressions."""
+    fields = ('node',)
+    operator = None
+    abstract = True
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        f = _uaop_to_func[self.operator]
+        try:
+            return f(self.node.as_const(eval_ctx))
+        except:
+            raise Impossible()
+
+
+class Name(Expr):
+    """Looks up a name or stores a value in a name.
+    The `ctx` of the node can be one of the following values:
+
+    -   `store`: store a value in the name
+    -   `load`: load that name
+    -   `param`: like `store` but if the name was defined as function parameter.
+    """
+    fields = ('name', 'ctx')
+
+    def can_assign(self):
+        return self.name not in ('true', 'false', 'none',
+                                 'True', 'False', 'None')
+
+
+class Literal(Expr):
+    """Baseclass for literals."""
+    abstract = True
+
+
+class Const(Literal):
+    """All constant values.  The parser will return this node for simple
+    constants such as ``42`` or ``"foo"`` but it can be used to store more
+    complex values such as lists too.  Only constants with a safe
+    representation (objects where ``eval(repr(x)) == x`` is true).
+    """
+    fields = ('value',)
+
+    def as_const(self, eval_ctx=None):
+        return self.value
+
+    @classmethod
+    def from_untrusted(cls, value, lineno=None, environment=None):
+        """Return a const object if the value is representable as
+        constant value in the generated code, otherwise it will raise
+        an `Impossible` exception.
+        """
+        from compiler import has_safe_repr
+        if not has_safe_repr(value):
+            raise Impossible()
+        return cls(value, lineno=lineno, environment=environment)
+
+
+class TemplateData(Literal):
+    """A constant template string."""
+    fields = ('data',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile:
+            raise Impossible()
+        if eval_ctx.autoescape:
+            return Markup(self.data)
+        return self.data
+
+
+class Tuple(Literal):
+    """For loop unpacking and some other things like multiple arguments
+    for subscripts.  Like for :class:`Name` `ctx` specifies if the tuple
+    is used for loading the names or storing.
+    """
+    fields = ('items', 'ctx')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return tuple(x.as_const(eval_ctx) for x in self.items)
+
+    def can_assign(self):
+        for item in self.items:
+            if not item.can_assign():
+                return False
+        return True
+
+
+class List(Literal):
+    """Any list literal such as ``[1, 2, 3]``"""
+    fields = ('items',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return [x.as_const(eval_ctx) for x in self.items]
+
+
+class Dict(Literal):
+    """Any dict literal such as ``{1: 2, 3: 4}``.  The items must be a list of
+    :class:`Pair` nodes.
+    """
+    fields = ('items',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return dict(x.as_const(eval_ctx) for x in self.items)
+
+
+class Pair(Helper):
+    """A key, value pair for dicts."""
+    fields = ('key', 'value')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
+
+
+class Keyword(Helper):
+    """A key, value pair for keyword arguments where key is a string."""
+    fields = ('key', 'value')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.key, self.value.as_const(eval_ctx)
+
+
+class CondExpr(Expr):
+    """A conditional expression (inline if expression).  (``{{
+    foo if bar else baz }}``)
+    """
+    fields = ('test', 'expr1', 'expr2')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if self.test.as_const(eval_ctx):
+            return self.expr1.as_const(eval_ctx)
+
+        # if we evaluate to an undefined object, we better do that at runtime
+        if self.expr2 is None:
+            raise Impossible()
+
+        return self.expr2.as_const(eval_ctx)
+
+
+class Filter(Expr):
+    """This node applies a filter on an expression.  `name` is the name of
+    the filter, the rest of the fields are the same as for :class:`Call`.
+
+    If the `node` of a filter is `None` the contents of the last buffer are
+    filtered.  Buffers are created by macros and filter blocks.
+    """
+    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile or self.node is None:
+            raise Impossible()
+        # we have to be careful here because we call filter_ below.
+        # if this variable would be called filter, 2to3 would wrap the
+        # call in a list beause it is assuming we are talking about the
+        # builtin filter function here which no longer returns a list in
+        # python 3.  because of that, do not rename filter_ to filter!
+        filter_ = self.environment.filters.get(self.name)
+        if filter_ is None or getattr(filter_, 'contextfilter', False):
+            raise Impossible()
+        obj = self.node.as_const(eval_ctx)
+        args = [x.as_const(eval_ctx) for x in self.args]
+        if getattr(filter_, 'evalcontextfilter', False):
+            args.insert(0, eval_ctx)
+        elif getattr(filter_, 'environmentfilter', False):
+            args.insert(0, self.environment)
+        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
+        if self.dyn_args is not None:
+            try:
+                args.extend(self.dyn_args.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        if self.dyn_kwargs is not None:
+            try:
+                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        try:
+            return filter_(obj, *args, **kwargs)
+        except:
+            raise Impossible()
+
+
+class Test(Expr):
+    """Applies a test on an expression.  `name` is the name of the test, the
+    rest of the fields are the same as for :class:`Call`.
+    """
+    fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+
+class Call(Expr):
+    """Calls an expression.  `args` is a list of arguments, `kwargs` a list
+    of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
+    and `dyn_kwargs` has to be either `None` or a node that is used as
+    node for dynamic positional (``*args``) or keyword (``**kwargs``)
+    arguments.
+    """
+    fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile:
+            raise Impossible()
+        obj = self.node.as_const(eval_ctx)
+
+        # don't evaluate context functions
+        args = [x.as_const(eval_ctx) for x in self.args]
+        if isinstance(obj, _context_function_types):
+            if getattr(obj, 'contextfunction', False):
+                raise Impossible()
+            elif getattr(obj, 'evalcontextfunction', False):
+                args.insert(0, eval_ctx)
+            elif getattr(obj, 'environmentfunction', False):
+                args.insert(0, self.environment)
+
+        kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
+        if self.dyn_args is not None:
+            try:
+                args.extend(self.dyn_args.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        if self.dyn_kwargs is not None:
+            try:
+                kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
+            except:
+                raise Impossible()
+        try:
+            return obj(*args, **kwargs)
+        except:
+            raise Impossible()
+
+
+class Getitem(Expr):
+    """Get an attribute or item from an expression and prefer the item."""
+    fields = ('node', 'arg', 'ctx')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if self.ctx != 'load':
+            raise Impossible()
+        try:
+            return self.environment.getitem(self.node.as_const(eval_ctx),
+                                            self.arg.as_const(eval_ctx))
+        except:
+            raise Impossible()
+
+    def can_assign(self):
+        return False
+
+
+class Getattr(Expr):
+    """Get an attribute or item from an expression that is a ascii-only
+    bytestring and prefer the attribute.
+    """
+    fields = ('node', 'attr', 'ctx')
+
+    def as_const(self, eval_ctx=None):
+        if self.ctx != 'load':
+            raise Impossible()
+        try:
+            eval_ctx = get_eval_context(self, eval_ctx)
+            return self.environment.getattr(self.node.as_const(eval_ctx),
+                                            self.attr)
+        except:
+            raise Impossible()
+
+    def can_assign(self):
+        return False
+
+
+class Slice(Expr):
+    """Represents a slice object.  This must only be used as argument for
+    :class:`Subscript`.
+    """
+    fields = ('start', 'stop', 'step')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        def const(obj):
+            if obj is None:
+                return None
+            return obj.as_const(eval_ctx)
+        return slice(const(self.start), const(self.stop), const(self.step))
+
+
+class Concat(Expr):
+    """Concatenates the list of expressions provided after converting them to
+    unicode.
+    """
+    fields = ('nodes',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes)
+
+
+class Compare(Expr):
+    """Compares an expression with some other expressions.  `ops` must be a
+    list of :class:`Operand`\s.
+    """
+    fields = ('expr', 'ops')
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        result = value = self.expr.as_const(eval_ctx)
+        try:
+            for op in self.ops:
+                new_value = op.expr.as_const(eval_ctx)
+                result = _cmpop_to_func[op.op](value, new_value)
+                value = new_value
+        except:
+            raise Impossible()
+        return result
+
+
+class Operand(Helper):
+    """Holds an operator and an expression."""
+    fields = ('op', 'expr')
+
+if __debug__:
+    Operand.__doc__ += '\nThe following operators are available: ' + \
+        ', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
+                  set(_uaop_to_func) | set(_cmpop_to_func)))
+
+
+class Mul(BinExpr):
+    """Multiplies the left with the right node."""
+    operator = '*'
+
+
+class Div(BinExpr):
+    """Divides the left by the right node."""
+    operator = '/'
+
+
+class FloorDiv(BinExpr):
+    """Divides the left by the right node and truncates conver the
+    result into an integer by truncating.
+    """
+    operator = '//'
+
+
+class Add(BinExpr):
+    """Add the left to the right node."""
+    operator = '+'
+
+
+class Sub(BinExpr):
+    """Substract the right from the left node."""
+    operator = '-'
+
+
+class Mod(BinExpr):
+    """Left modulo right."""
+    operator = '%'
+
+
+class Pow(BinExpr):
+    """Left to the power of right."""
+    operator = '**'
+
+
+class And(BinExpr):
+    """Short circuited AND."""
+    operator = 'and'
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx)
+
+
+class Or(BinExpr):
+    """Short circuited OR."""
+    operator = 'or'
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx)
+
+
+class Not(UnaryExpr):
+    """Negate the expression."""
+    operator = 'not'
+
+
+class Neg(UnaryExpr):
+    """Make the expression negative."""
+    operator = '-'
+
+
+class Pos(UnaryExpr):
+    """Make the expression positive (noop for most expressions)"""
+    operator = '+'
+
+
+# Helpers for extensions
+
+
+class EnvironmentAttribute(Expr):
+    """Loads an attribute from the environment object.  This is useful for
+    extensions that want to call a callback stored on the environment.
+    """
+    fields = ('name',)
+
+
+class ExtensionAttribute(Expr):
+    """Returns the attribute of an extension bound to the environment.
+    The identifier is the identifier of the :class:`Extension`.
+
+    This node is usually constructed by calling the
+    :meth:`~jinja2.ext.Extension.attr` method on an extension.
+    """
+    fields = ('identifier', 'name')
+
+
+class ImportedName(Expr):
+    """If created with an import name the import name is returned on node
+    access.  For example ``ImportedName('cgi.escape')`` returns the `escape`
+    function from the cgi module on evaluation.  Imports are optimized by the
+    compiler so there is no need to assign them to local variables.
+    """
+    fields = ('importname',)
+
+
+class InternalName(Expr):
+    """An internal name in the compiler.  You cannot create these nodes
+    yourself but the parser provides a
+    :meth:`~jinja2.parser.Parser.free_identifier` method that creates
+    a new identifier for you.  This identifier is not available from the
+    template and is not threated specially by the compiler.
+    """
+    fields = ('name',)
+
+    def __init__(self):
+        raise TypeError('Can\'t create internal names.  Use the '
+                        '`free_identifier` method on a parser.')
+
+
+class MarkSafe(Expr):
+    """Mark the wrapped expression as safe (wrap it as `Markup`)."""
+    fields = ('expr',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        return Markup(self.expr.as_const(eval_ctx))
+
+
+class MarkSafeIfAutoescape(Expr):
+    """Mark the wrapped expression as safe (wrap it as `Markup`) but
+    only if autoescaping is active.
+
+    .. versionadded:: 2.5
+    """
+    fields = ('expr',)
+
+    def as_const(self, eval_ctx=None):
+        eval_ctx = get_eval_context(self, eval_ctx)
+        if eval_ctx.volatile:
+            raise Impossible()
+        expr = self.expr.as_const(eval_ctx)
+        if eval_ctx.autoescape:
+            return Markup(expr)
+        return expr
+
+
+class ContextReference(Expr):
+    """Returns the current template context.  It can be used like a
+    :class:`Name` node, with a ``'load'`` ctx and will return the
+    current :class:`~jinja2.runtime.Context` object.
+
+    Here an example that assigns the current template name to a
+    variable named `foo`::
+
+        Assign(Name('foo', ctx='store'),
+               Getattr(ContextReference(), 'name'))
+    """
+
+
+class Continue(Stmt):
+    """Continue a loop."""
+
+
+class Break(Stmt):
+    """Break a loop."""
+
+
+class Scope(Stmt):
+    """An artificial scope."""
+    fields = ('body',)
+
+
+class EvalContextModifier(Stmt):
+    """Modifies the eval context.  For each option that should be modified,
+    a :class:`Keyword` has to be added to the :attr:`options` list.
+
+    Example to change the `autoescape` setting::
+
+        EvalContextModifier(options=[Keyword('autoescape', Const(True))])
+    """
+    fields = ('options',)
+
+
+class ScopedEvalContextModifier(EvalContextModifier):
+    """Modifies the eval context and reverts it later.  Works exactly like
+    :class:`EvalContextModifier` but will only modify the
+    :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
+    """
+    fields = ('body',)
+
+
+# make sure nobody creates custom nodes
+def _failing_new(*args, **kwargs):
+    raise TypeError('can\'t create custom node types')
+NodeType.__new__ = staticmethod(_failing_new); del _failing_new

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/optimizer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/optimizer.py b/ambari-common/src/main/python/jinja2/jinja2/optimizer.py
new file mode 100644
index 0000000..00eab11
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/optimizer.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.optimizer
+    ~~~~~~~~~~~~~~~~
+
+    The jinja optimizer is currently trying to constant fold a few expressions
+    and modify the AST in place so that it should be easier to evaluate it.
+
+    Because the AST does not contain all the scoping information and the
+    compiler has to find that out, we cannot do all the optimizations we
+    want.  For example loop unrolling doesn't work because unrolled loops would
+    have a different scoping.
+
+    The solution would be a second syntax tree that has the scoping rules stored.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from jinja2 import nodes
+from jinja2.visitor import NodeTransformer
+
+
+def optimize(node, environment):
+    """The context hint can be used to perform an static optimization
+    based on the context given."""
+    optimizer = Optimizer(environment)
+    return optimizer.visit(node)
+
+
+class Optimizer(NodeTransformer):
+
+    def __init__(self, environment):
+        self.environment = environment
+
+    def visit_If(self, node):
+        """Eliminate dead code."""
+        # do not optimize ifs that have a block inside so that it doesn't
+        # break super().
+        if node.find(nodes.Block) is not None:
+            return self.generic_visit(node)
+        try:
+            val = self.visit(node.test).as_const()
+        except nodes.Impossible:
+            return self.generic_visit(node)
+        if val:
+            body = node.body
+        else:
+            body = node.else_
+        result = []
+        for node in body:
+            result.extend(self.visit_list(node))
+        return result
+
+    def fold(self, node):
+        """Do constant folding."""
+        node = self.generic_visit(node)
+        try:
+            return nodes.Const.from_untrusted(node.as_const(),
+                                              lineno=node.lineno,
+                                              environment=self.environment)
+        except nodes.Impossible:
+            return node
+
+    visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
+    visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
+    visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \
+    visit_Filter = visit_Test = visit_CondExpr = fold
+    del fold

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/parser.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/parser.py b/ambari-common/src/main/python/jinja2/jinja2/parser.py
new file mode 100644
index 0000000..d44229a
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/parser.py
@@ -0,0 +1,896 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.parser
+    ~~~~~~~~~~~~~
+
+    Implements the template parser.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from jinja2 import nodes
+from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
+from jinja2.utils import next
+from jinja2.lexer import describe_token, describe_token_expr
+
+
+#: statements that callinto 
+_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
+                                 'macro', 'include', 'from', 'import',
+                                 'set'])
+_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
+
+
+class Parser(object):
+    """This is the central parsing class Jinja2 uses.  It's passed to
+    extensions and can be used to parse expressions or statements.
+    """
+
+    def __init__(self, environment, source, name=None, filename=None,
+                 state=None):
+        self.environment = environment
+        self.stream = environment._tokenize(source, name, filename, state)
+        self.name = name
+        self.filename = filename
+        self.closed = False
+        self.extensions = {}
+        for extension in environment.iter_extensions():
+            for tag in extension.tags:
+                self.extensions[tag] = extension.parse
+        self._last_identifier = 0
+        self._tag_stack = []
+        self._end_token_stack = []
+
+    def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
+        """Convenience method that raises `exc` with the message, passed
+        line number or last line number as well as the current name and
+        filename.
+        """
+        if lineno is None:
+            lineno = self.stream.current.lineno
+        raise exc(msg, lineno, self.name, self.filename)
+
+    def _fail_ut_eof(self, name, end_token_stack, lineno):
+        expected = []
+        for exprs in end_token_stack:
+            expected.extend(map(describe_token_expr, exprs))
+        if end_token_stack:
+            currently_looking = ' or '.join(
+                "'%s'" % describe_token_expr(expr)
+                for expr in end_token_stack[-1])
+        else:
+            currently_looking = None
+
+        if name is None:
+            message = ['Unexpected end of template.']
+        else:
+            message = ['Encountered unknown tag \'%s\'.' % name]
+
+        if currently_looking:
+            if name is not None and name in expected:
+                message.append('You probably made a nesting mistake. Jinja '
+                               'is expecting this tag, but currently looking '
+                               'for %s.' % currently_looking)
+            else:
+                message.append('Jinja was looking for the following tags: '
+                               '%s.' % currently_looking)
+
+        if self._tag_stack:
+            message.append('The innermost block that needs to be '
+                           'closed is \'%s\'.' % self._tag_stack[-1])
+
+        self.fail(' '.join(message), lineno)
+
+    def fail_unknown_tag(self, name, lineno=None):
+        """Called if the parser encounters an unknown tag.  Tries to fail
+        with a human readable error message that could help to identify
+        the problem.
+        """
+        return self._fail_ut_eof(name, self._end_token_stack, lineno)
+
+    def fail_eof(self, end_tokens=None, lineno=None):
+        """Like fail_unknown_tag but for end of template situations."""
+        stack = list(self._end_token_stack)
+        if end_tokens is not None:
+            stack.append(end_tokens)
+        return self._fail_ut_eof(None, stack, lineno)
+
+    def is_tuple_end(self, extra_end_rules=None):
+        """Are we at the end of a tuple?"""
+        if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
+            return True
+        elif extra_end_rules is not None:
+            return self.stream.current.test_any(extra_end_rules)
+        return False
+
+    def free_identifier(self, lineno=None):
+        """Return a new free identifier as :class:`~jinja2.nodes.InternalName`."""
+        self._last_identifier += 1
+        rv = object.__new__(nodes.InternalName)
+        nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
+        return rv
+
+    def parse_statement(self):
+        """Parse a single statement."""
+        token = self.stream.current
+        if token.type != 'name':
+            self.fail('tag name expected', token.lineno)
+        self._tag_stack.append(token.value)
+        pop_tag = True
+        try:
+            if token.value in _statement_keywords:
+                return getattr(self, 'parse_' + self.stream.current.value)()
+            if token.value == 'call':
+                return self.parse_call_block()
+            if token.value == 'filter':
+                return self.parse_filter_block()
+            ext = self.extensions.get(token.value)
+            if ext is not None:
+                return ext(self)
+
+            # did not work out, remove the token we pushed by accident
+            # from the stack so that the unknown tag fail function can
+            # produce a proper error message.
+            self._tag_stack.pop()
+            pop_tag = False
+            self.fail_unknown_tag(token.value, token.lineno)
+        finally:
+            if pop_tag:
+                self._tag_stack.pop()
+
+    def parse_statements(self, end_tokens, drop_needle=False):
+        """Parse multiple statements into a list until one of the end tokens
+        is reached.  This is used to parse the body of statements as it also
+        parses template data if appropriate.  The parser checks first if the
+        current token is a colon and skips it if there is one.  Then it checks
+        for the block end and parses until if one of the `end_tokens` is
+        reached.  Per default the active token in the stream at the end of
+        the call is the matched end token.  If this is not wanted `drop_needle`
+        can be set to `True` and the end token is removed.
+        """
+        # the first token may be a colon for python compatibility
+        self.stream.skip_if('colon')
+
+        # in the future it would be possible to add whole code sections
+        # by adding some sort of end of statement token and parsing those here.
+        self.stream.expect('block_end')
+        result = self.subparse(end_tokens)
+
+        # we reached the end of the template too early, the subparser
+        # does not check for this, so we do that now
+        if self.stream.current.type == 'eof':
+            self.fail_eof(end_tokens)
+
+        if drop_needle:
+            next(self.stream)
+        return result
+
+    def parse_set(self):
+        """Parse an assign statement."""
+        lineno = next(self.stream).lineno
+        target = self.parse_assign_target()
+        self.stream.expect('assign')
+        expr = self.parse_tuple()
+        return nodes.Assign(target, expr, lineno=lineno)
+
+    def parse_for(self):
+        """Parse a for loop."""
+        lineno = self.stream.expect('name:for').lineno
+        target = self.parse_assign_target(extra_end_rules=('name:in',))
+        self.stream.expect('name:in')
+        iter = self.parse_tuple(with_condexpr=False,
+                                extra_end_rules=('name:recursive',))
+        test = None
+        if self.stream.skip_if('name:if'):
+            test = self.parse_expression()
+        recursive = self.stream.skip_if('name:recursive')
+        body = self.parse_statements(('name:endfor', 'name:else'))
+        if next(self.stream).value == 'endfor':
+            else_ = []
+        else:
+            else_ = self.parse_statements(('name:endfor',), drop_needle=True)
+        return nodes.For(target, iter, body, else_, test,
+                         recursive, lineno=lineno)
+
+    def parse_if(self):
+        """Parse an if construct."""
+        node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
+        while 1:
+            node.test = self.parse_tuple(with_condexpr=False)
+            node.body = self.parse_statements(('name:elif', 'name:else',
+                                               'name:endif'))
+            token = next(self.stream)
+            if token.test('name:elif'):
+                new_node = nodes.If(lineno=self.stream.current.lineno)
+                node.else_ = [new_node]
+                node = new_node
+                continue
+            elif token.test('name:else'):
+                node.else_ = self.parse_statements(('name:endif',),
+                                                   drop_needle=True)
+            else:
+                node.else_ = []
+            break
+        return result
+
+    def parse_block(self):
+        node = nodes.Block(lineno=next(self.stream).lineno)
+        node.name = self.stream.expect('name').value
+        node.scoped = self.stream.skip_if('name:scoped')
+
+        # common problem people encounter when switching from django
+        # to jinja.  we do not support hyphens in block names, so let's
+        # raise a nicer error message in that case.
+        if self.stream.current.type == 'sub':
+            self.fail('Block names in Jinja have to be valid Python '
+                      'identifiers and may not contain hypens, use an '
+                      'underscore instead.')
+
+        node.body = self.parse_statements(('name:endblock',), drop_needle=True)
+        self.stream.skip_if('name:' + node.name)
+        return node
+
+    def parse_extends(self):
+        node = nodes.Extends(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        return node
+
+    def parse_import_context(self, node, default):
+        if self.stream.current.test_any('name:with', 'name:without') and \
+           self.stream.look().test('name:context'):
+            node.with_context = next(self.stream).value == 'with'
+            self.stream.skip()
+        else:
+            node.with_context = default
+        return node
+
+    def parse_include(self):
+        node = nodes.Include(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        if self.stream.current.test('name:ignore') and \
+           self.stream.look().test('name:missing'):
+            node.ignore_missing = True
+            self.stream.skip(2)
+        else:
+            node.ignore_missing = False
+        return self.parse_import_context(node, True)
+
+    def parse_import(self):
+        node = nodes.Import(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        self.stream.expect('name:as')
+        node.target = self.parse_assign_target(name_only=True).name
+        return self.parse_import_context(node, False)
+
+    def parse_from(self):
+        node = nodes.FromImport(lineno=next(self.stream).lineno)
+        node.template = self.parse_expression()
+        self.stream.expect('name:import')
+        node.names = []
+
+        def parse_context():
+            if self.stream.current.value in ('with', 'without') and \
+               self.stream.look().test('name:context'):
+                node.with_context = next(self.stream).value == 'with'
+                self.stream.skip()
+                return True
+            return False
+
+        while 1:
+            if node.names:
+                self.stream.expect('comma')
+            if self.stream.current.type == 'name':
+                if parse_context():
+                    break
+                target = self.parse_assign_target(name_only=True)
+                if target.name.startswith('_'):
+                    self.fail('names starting with an underline can not '
+                              'be imported', target.lineno,
+                              exc=TemplateAssertionError)
+                if self.stream.skip_if('name:as'):
+                    alias = self.parse_assign_target(name_only=True)
+                    node.names.append((target.name, alias.name))
+                else:
+                    node.names.append(target.name)
+                if parse_context() or self.stream.current.type != 'comma':
+                    break
+            else:
+                break
+        if not hasattr(node, 'with_context'):
+            node.with_context = False
+            self.stream.skip_if('comma')
+        return node
+
+    def parse_signature(self, node):
+        node.args = args = []
+        node.defaults = defaults = []
+        self.stream.expect('lparen')
+        while self.stream.current.type != 'rparen':
+            if args:
+                self.stream.expect('comma')
+            arg = self.parse_assign_target(name_only=True)
+            arg.set_ctx('param')
+            if self.stream.skip_if('assign'):
+                defaults.append(self.parse_expression())
+            args.append(arg)
+        self.stream.expect('rparen')
+
+    def parse_call_block(self):
+        node = nodes.CallBlock(lineno=next(self.stream).lineno)
+        if self.stream.current.type == 'lparen':
+            self.parse_signature(node)
+        else:
+            node.args = []
+            node.defaults = []
+
+        node.call = self.parse_expression()
+        if not isinstance(node.call, nodes.Call):
+            self.fail('expected call', node.lineno)
+        node.body = self.parse_statements(('name:endcall',), drop_needle=True)
+        return node
+
+    def parse_filter_block(self):
+        node = nodes.FilterBlock(lineno=next(self.stream).lineno)
+        node.filter = self.parse_filter(None, start_inline=True)
+        node.body = self.parse_statements(('name:endfilter',),
+                                          drop_needle=True)
+        return node
+
+    def parse_macro(self):
+        node = nodes.Macro(lineno=next(self.stream).lineno)
+        node.name = self.parse_assign_target(name_only=True).name
+        self.parse_signature(node)
+        node.body = self.parse_statements(('name:endmacro',),
+                                          drop_needle=True)
+        return node
+
+    def parse_print(self):
+        node = nodes.Output(lineno=next(self.stream).lineno)
+        node.nodes = []
+        while self.stream.current.type != 'block_end':
+            if node.nodes:
+                self.stream.expect('comma')
+            node.nodes.append(self.parse_expression())
+        return node
+
+    def parse_assign_target(self, with_tuple=True, name_only=False,
+                            extra_end_rules=None):
+        """Parse an assignment target.  As Jinja2 allows assignments to
+        tuples, this function can parse all allowed assignment targets.  Per
+        default assignments to tuples are parsed, that can be disable however
+        by setting `with_tuple` to `False`.  If only assignments to names are
+        wanted `name_only` can be set to `True`.  The `extra_end_rules`
+        parameter is forwarded to the tuple parsing function.
+        """
+        if name_only:
+            token = self.stream.expect('name')
+            target = nodes.Name(token.value, 'store', lineno=token.lineno)
+        else:
+            if with_tuple:
+                target = self.parse_tuple(simplified=True,
+                                          extra_end_rules=extra_end_rules)
+            else:
+                target = self.parse_primary()
+            target.set_ctx('store')
+        if not target.can_assign():
+            self.fail('can\'t assign to %r' % target.__class__.
+                      __name__.lower(), target.lineno)
+        return target
+
+    def parse_expression(self, with_condexpr=True):
+        """Parse an expression.  Per default all expressions are parsed, if
+        the optional `with_condexpr` parameter is set to `False` conditional
+        expressions are not parsed.
+        """
+        if with_condexpr:
+            return self.parse_condexpr()
+        return self.parse_or()
+
+    def parse_condexpr(self):
+        lineno = self.stream.current.lineno
+        expr1 = self.parse_or()
+        while self.stream.skip_if('name:if'):
+            expr2 = self.parse_or()
+            if self.stream.skip_if('name:else'):
+                expr3 = self.parse_condexpr()
+            else:
+                expr3 = None
+            expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return expr1
+
+    def parse_or(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_and()
+        while self.stream.skip_if('name:or'):
+            right = self.parse_and()
+            left = nodes.Or(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_and(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_not()
+        while self.stream.skip_if('name:and'):
+            right = self.parse_not()
+            left = nodes.And(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_not(self):
+        if self.stream.current.test('name:not'):
+            lineno = next(self.stream).lineno
+            return nodes.Not(self.parse_not(), lineno=lineno)
+        return self.parse_compare()
+
+    def parse_compare(self):
+        lineno = self.stream.current.lineno
+        expr = self.parse_add()
+        ops = []
+        while 1:
+            token_type = self.stream.current.type
+            if token_type in _compare_operators:
+                next(self.stream)
+                ops.append(nodes.Operand(token_type, self.parse_add()))
+            elif self.stream.skip_if('name:in'):
+                ops.append(nodes.Operand('in', self.parse_add()))
+            elif self.stream.current.test('name:not') and \
+                 self.stream.look().test('name:in'):
+                self.stream.skip(2)
+                ops.append(nodes.Operand('notin', self.parse_add()))
+            else:
+                break
+            lineno = self.stream.current.lineno
+        if not ops:
+            return expr
+        return nodes.Compare(expr, ops, lineno=lineno)
+
+    def parse_add(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_sub()
+        while self.stream.current.type == 'add':
+            next(self.stream)
+            right = self.parse_sub()
+            left = nodes.Add(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_sub(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_concat()
+        while self.stream.current.type == 'sub':
+            next(self.stream)
+            right = self.parse_concat()
+            left = nodes.Sub(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_concat(self):
+        lineno = self.stream.current.lineno
+        args = [self.parse_mul()]
+        while self.stream.current.type == 'tilde':
+            next(self.stream)
+            args.append(self.parse_mul())
+        if len(args) == 1:
+            return args[0]
+        return nodes.Concat(args, lineno=lineno)
+
+    def parse_mul(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_div()
+        while self.stream.current.type == 'mul':
+            next(self.stream)
+            right = self.parse_div()
+            left = nodes.Mul(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_div(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_floordiv()
+        while self.stream.current.type == 'div':
+            next(self.stream)
+            right = self.parse_floordiv()
+            left = nodes.Div(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_floordiv(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_mod()
+        while self.stream.current.type == 'floordiv':
+            next(self.stream)
+            right = self.parse_mod()
+            left = nodes.FloorDiv(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_mod(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_pow()
+        while self.stream.current.type == 'mod':
+            next(self.stream)
+            right = self.parse_pow()
+            left = nodes.Mod(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_pow(self):
+        lineno = self.stream.current.lineno
+        left = self.parse_unary()
+        while self.stream.current.type == 'pow':
+            next(self.stream)
+            right = self.parse_unary()
+            left = nodes.Pow(left, right, lineno=lineno)
+            lineno = self.stream.current.lineno
+        return left
+
+    def parse_unary(self, with_filter=True):
+        token_type = self.stream.current.type
+        lineno = self.stream.current.lineno
+        if token_type == 'sub':
+            next(self.stream)
+            node = nodes.Neg(self.parse_unary(False), lineno=lineno)
+        elif token_type == 'add':
+            next(self.stream)
+            node = nodes.Pos(self.parse_unary(False), lineno=lineno)
+        else:
+            node = self.parse_primary()
+        node = self.parse_postfix(node)
+        if with_filter:
+            node = self.parse_filter_expr(node)
+        return node
+
+    def parse_primary(self):
+        token = self.stream.current
+        if token.type == 'name':
+            if token.value in ('true', 'false', 'True', 'False'):
+                node = nodes.Const(token.value in ('true', 'True'),
+                                   lineno=token.lineno)
+            elif token.value in ('none', 'None'):
+                node = nodes.Const(None, lineno=token.lineno)
+            else:
+                node = nodes.Name(token.value, 'load', lineno=token.lineno)
+            next(self.stream)
+        elif token.type == 'string':
+            next(self.stream)
+            buf = [token.value]
+            lineno = token.lineno
+            while self.stream.current.type == 'string':
+                buf.append(self.stream.current.value)
+                next(self.stream)
+            node = nodes.Const(''.join(buf), lineno=lineno)
+        elif token.type in ('integer', 'float'):
+            next(self.stream)
+            node = nodes.Const(token.value, lineno=token.lineno)
+        elif token.type == 'lparen':
+            next(self.stream)
+            node = self.parse_tuple(explicit_parentheses=True)
+            self.stream.expect('rparen')
+        elif token.type == 'lbracket':
+            node = self.parse_list()
+        elif token.type == 'lbrace':
+            node = self.parse_dict()
+        else:
+            self.fail("unexpected '%s'" % describe_token(token), token.lineno)
+        return node
+
+    def parse_tuple(self, simplified=False, with_condexpr=True,
+                    extra_end_rules=None, explicit_parentheses=False):
+        """Works like `parse_expression` but if multiple expressions are
+        delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
+        This method could also return a regular expression instead of a tuple
+        if no commas where found.
+
+        The default parsing mode is a full tuple.  If `simplified` is `True`
+        only names and literals are parsed.  The `no_condexpr` parameter is
+        forwarded to :meth:`parse_expression`.
+
+        Because tuples do not require delimiters and may end in a bogus comma
+        an extra hint is needed that marks the end of a tuple.  For example
+        for loops support tuples between `for` and `in`.  In that case the
+        `extra_end_rules` is set to ``['name:in']``.
+
+        `explicit_parentheses` is true if the parsing was triggered by an
+        expression in parentheses.  This is used to figure out if an empty
+        tuple is a valid expression or not.
+        """
+        lineno = self.stream.current.lineno
+        if simplified:
+            parse = self.parse_primary
+        elif with_condexpr:
+            parse = self.parse_expression
+        else:
+            parse = lambda: self.parse_expression(with_condexpr=False)
+        args = []
+        is_tuple = False
+        while 1:
+            if args:
+                self.stream.expect('comma')
+            if self.is_tuple_end(extra_end_rules):
+                break
+            args.append(parse())
+            if self.stream.current.type == 'comma':
+                is_tuple = True
+            else:
+                break
+            lineno = self.stream.current.lineno
+
+        if not is_tuple:
+            if args:
+                return args[0]
+
+            # if we don't have explicit parentheses, an empty tuple is
+            # not a valid expression.  This would mean nothing (literally
+            # nothing) in the spot of an expression would be an empty
+            # tuple.
+            if not explicit_parentheses:
+                self.fail('Expected an expression, got \'%s\'' %
+                          describe_token(self.stream.current))
+
+        return nodes.Tuple(args, 'load', lineno=lineno)
+
+    def parse_list(self):
+        token = self.stream.expect('lbracket')
+        items = []
+        while self.stream.current.type != 'rbracket':
+            if items:
+                self.stream.expect('comma')
+            if self.stream.current.type == 'rbracket':
+                break
+            items.append(self.parse_expression())
+        self.stream.expect('rbracket')
+        return nodes.List(items, lineno=token.lineno)
+
+    def parse_dict(self):
+        token = self.stream.expect('lbrace')
+        items = []
+        while self.stream.current.type != 'rbrace':
+            if items:
+                self.stream.expect('comma')
+            if self.stream.current.type == 'rbrace':
+                break
+            key = self.parse_expression()
+            self.stream.expect('colon')
+            value = self.parse_expression()
+            items.append(nodes.Pair(key, value, lineno=key.lineno))
+        self.stream.expect('rbrace')
+        return nodes.Dict(items, lineno=token.lineno)
+
+    def parse_postfix(self, node):
+        while 1:
+            token_type = self.stream.current.type
+            if token_type == 'dot' or token_type == 'lbracket':
+                node = self.parse_subscript(node)
+            # calls are valid both after postfix expressions (getattr
+            # and getitem) as well as filters and tests
+            elif token_type == 'lparen':
+                node = self.parse_call(node)
+            else:
+                break
+        return node
+
+    def parse_filter_expr(self, node):
+        while 1:
+            token_type = self.stream.current.type
+            if token_type == 'pipe':
+                node = self.parse_filter(node)
+            elif token_type == 'name' and self.stream.current.value == 'is':
+                node = self.parse_test(node)
+            # calls are valid both after postfix expressions (getattr
+            # and getitem) as well as filters and tests
+            elif token_type == 'lparen':
+                node = self.parse_call(node)
+            else:
+                break
+        return node
+
+    def parse_subscript(self, node):
+        token = next(self.stream)
+        if token.type == 'dot':
+            attr_token = self.stream.current
+            next(self.stream)
+            if attr_token.type == 'name':
+                return nodes.Getattr(node, attr_token.value, 'load',
+                                     lineno=token.lineno)
+            elif attr_token.type != 'integer':
+                self.fail('expected name or number', attr_token.lineno)
+            arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
+            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
+        if token.type == 'lbracket':
+            priority_on_attribute = False
+            args = []
+            while self.stream.current.type != 'rbracket':
+                if args:
+                    self.stream.expect('comma')
+                args.append(self.parse_subscribed())
+            self.stream.expect('rbracket')
+            if len(args) == 1:
+                arg = args[0]
+            else:
+                arg = nodes.Tuple(args, 'load', lineno=token.lineno)
+            return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
+        self.fail('expected subscript expression', self.lineno)
+
+    def parse_subscribed(self):
+        lineno = self.stream.current.lineno
+
+        if self.stream.current.type == 'colon':
+            next(self.stream)
+            args = [None]
+        else:
+            node = self.parse_expression()
+            if self.stream.current.type != 'colon':
+                return node
+            next(self.stream)
+            args = [node]
+
+        if self.stream.current.type == 'colon':
+            args.append(None)
+        elif self.stream.current.type not in ('rbracket', 'comma'):
+            args.append(self.parse_expression())
+        else:
+            args.append(None)
+
+        if self.stream.current.type == 'colon':
+            next(self.stream)
+            if self.stream.current.type not in ('rbracket', 'comma'):
+                args.append(self.parse_expression())
+            else:
+                args.append(None)
+        else:
+            args.append(None)
+
+        return nodes.Slice(lineno=lineno, *args)
+
+    def parse_call(self, node):
+        token = self.stream.expect('lparen')
+        args = []
+        kwargs = []
+        dyn_args = dyn_kwargs = None
+        require_comma = False
+
+        def ensure(expr):
+            if not expr:
+                self.fail('invalid syntax for function call expression',
+                          token.lineno)
+
+        while self.stream.current.type != 'rparen':
+            if require_comma:
+                self.stream.expect('comma')
+                # support for trailing comma
+                if self.stream.current.type == 'rparen':
+                    break
+            if self.stream.current.type == 'mul':
+                ensure(dyn_args is None and dyn_kwargs is None)
+                next(self.stream)
+                dyn_args = self.parse_expression()
+            elif self.stream.current.type == 'pow':
+                ensure(dyn_kwargs is None)
+                next(self.stream)
+                dyn_kwargs = self.parse_expression()
+            else:
+                ensure(dyn_args is None and dyn_kwargs is None)
+                if self.stream.current.type == 'name' and \
+                    self.stream.look().type == 'assign':
+                    key = self.stream.current.value
+                    self.stream.skip(2)
+                    value = self.parse_expression()
+                    kwargs.append(nodes.Keyword(key, value,
+                                                lineno=value.lineno))
+                else:
+                    ensure(not kwargs)
+                    args.append(self.parse_expression())
+
+            require_comma = True
+        self.stream.expect('rparen')
+
+        if node is None:
+            return args, kwargs, dyn_args, dyn_kwargs
+        return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
+                          lineno=token.lineno)
+
+    def parse_filter(self, node, start_inline=False):
+        while self.stream.current.type == 'pipe' or start_inline:
+            if not start_inline:
+                next(self.stream)
+            token = self.stream.expect('name')
+            name = token.value
+            while self.stream.current.type == 'dot':
+                next(self.stream)
+                name += '.' + self.stream.expect('name').value
+            if self.stream.current.type == 'lparen':
+                args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
+            else:
+                args = []
+                kwargs = []
+                dyn_args = dyn_kwargs = None
+            node = nodes.Filter(node, name, args, kwargs, dyn_args,
+                                dyn_kwargs, lineno=token.lineno)
+            start_inline = False
+        return node
+
+    def parse_test(self, node):
+        token = next(self.stream)
+        if self.stream.current.test('name:not'):
+            next(self.stream)
+            negated = True
+        else:
+            negated = False
+        name = self.stream.expect('name').value
+        while self.stream.current.type == 'dot':
+            next(self.stream)
+            name += '.' + self.stream.expect('name').value
+        dyn_args = dyn_kwargs = None
+        kwargs = []
+        if self.stream.current.type == 'lparen':
+            args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
+        elif self.stream.current.type in ('name', 'string', 'integer',
+                                          'float', 'lparen', 'lbracket',
+                                          'lbrace') and not \
+             self.stream.current.test_any('name:else', 'name:or',
+                                          'name:and'):
+            if self.stream.current.test('name:is'):
+                self.fail('You cannot chain multiple tests with is')
+            args = [self.parse_expression()]
+        else:
+            args = []
+        node = nodes.Test(node, name, args, kwargs, dyn_args,
+                          dyn_kwargs, lineno=token.lineno)
+        if negated:
+            node = nodes.Not(node, lineno=token.lineno)
+        return node
+
+    def subparse(self, end_tokens=None):
+        body = []
+        data_buffer = []
+        add_data = data_buffer.append
+
+        if end_tokens is not None:
+            self._end_token_stack.append(end_tokens)
+
+        def flush_data():
+            if data_buffer:
+                lineno = data_buffer[0].lineno
+                body.append(nodes.Output(data_buffer[:], lineno=lineno))
+                del data_buffer[:]
+
+        try:
+            while self.stream:
+                token = self.stream.current
+                if token.type == 'data':
+                    if token.value:
+                        add_data(nodes.TemplateData(token.value,
+                                                    lineno=token.lineno))
+                    next(self.stream)
+                elif token.type == 'variable_begin':
+                    next(self.stream)
+                    add_data(self.parse_tuple(with_condexpr=True))
+                    self.stream.expect('variable_end')
+                elif token.type == 'block_begin':
+                    flush_data()
+                    next(self.stream)
+                    if end_tokens is not None and \
+                       self.stream.current.test_any(*end_tokens):
+                        return body
+                    rv = self.parse_statement()
+                    if isinstance(rv, list):
+                        body.extend(rv)
+                    else:
+                        body.append(rv)
+                    self.stream.expect('block_end')
+                else:
+                    raise AssertionError('internal parsing error')
+
+            flush_data()
+        finally:
+            if end_tokens is not None:
+                self._end_token_stack.pop()
+
+        return body
+
+    def parse(self):
+        """Parse the whole template into a `Template` node."""
+        result = nodes.Template(self.subparse(), lineno=1)
+        result.set_environment(self.environment)
+        return result

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/runtime.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/runtime.py b/ambari-common/src/main/python/jinja2/jinja2/runtime.py
new file mode 100644
index 0000000..6fea3aa
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/runtime.py
@@ -0,0 +1,544 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.runtime
+    ~~~~~~~~~~~~~~
+
+    Runtime helpers.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+import sys
+from itertools import chain, imap
+from jinja2.nodes import EvalContext, _context_function_types
+from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
+     concat, internalcode, next, object_type_repr
+from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
+     TemplateNotFound
+
+
+# these variables are exported to the template runtime
+__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
+           'TemplateRuntimeError', 'missing', 'concat', 'escape',
+           'markup_join', 'unicode_join', 'to_string', 'identity',
+           'TemplateNotFound']
+
+#: the name of the function that is used to convert something into
+#: a string.  2to3 will adopt that automatically and the generated
+#: code can take advantage of it.
+to_string = unicode
+
+#: the identity function.  Useful for certain things in the environment
+identity = lambda x: x
+
+
+def markup_join(seq):
+    """Concatenation that escapes if necessary and converts to unicode."""
+    buf = []
+    iterator = imap(soft_unicode, seq)
+    for arg in iterator:
+        buf.append(arg)
+        if hasattr(arg, '__html__'):
+            return Markup(u'').join(chain(buf, iterator))
+    return concat(buf)
+
+
+def unicode_join(seq):
+    """Simple args to unicode conversion and concatenation."""
+    return concat(imap(unicode, seq))
+
+
+def new_context(environment, template_name, blocks, vars=None,
+                shared=None, globals=None, locals=None):
+    """Internal helper to for context creation."""
+    if vars is None:
+        vars = {}
+    if shared:
+        parent = vars
+    else:
+        parent = dict(globals or (), **vars)
+    if locals:
+        # if the parent is shared a copy should be created because
+        # we don't want to modify the dict passed
+        if shared:
+            parent = dict(parent)
+        for key, value in locals.iteritems():
+            if key[:2] == 'l_' and value is not missing:
+                parent[key[2:]] = value
+    return Context(environment, parent, template_name, blocks)
+
+
+class TemplateReference(object):
+    """The `self` in templates."""
+
+    def __init__(self, context):
+        self.__context = context
+
+    def __getitem__(self, name):
+        blocks = self.__context.blocks[name]
+        wrap = self.__context.eval_ctx.autoescape and \
+               Markup or (lambda x: x)
+        return BlockReference(name, self.__context, blocks, 0)
+
+    def __repr__(self):
+        return '<%s %r>' % (
+            self.__class__.__name__,
+            self.__context.name
+        )
+
+
+class Context(object):
+    """The template context holds the variables of a template.  It stores the
+    values passed to the template and also the names the template exports.
+    Creating instances is neither supported nor useful as it's created
+    automatically at various stages of the template evaluation and should not
+    be created by hand.
+
+    The context is immutable.  Modifications on :attr:`parent` **must not**
+    happen and modifications on :attr:`vars` are allowed from generated
+    template code only.  Template filters and global functions marked as
+    :func:`contextfunction`\s get the active context passed as first argument
+    and are allowed to access the context read-only.
+
+    The template context supports read only dict operations (`get`,
+    `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
+    `__getitem__`, `__contains__`).  Additionally there is a :meth:`resolve`
+    method that doesn't fail with a `KeyError` but returns an
+    :class:`Undefined` object for missing variables.
+    """
+    __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
+                 'name', 'blocks', '__weakref__')
+
+    def __init__(self, environment, parent, name, blocks):
+        self.parent = parent
+        self.vars = {}
+        self.environment = environment
+        self.eval_ctx = EvalContext(self.environment, name)
+        self.exported_vars = set()
+        self.name = name
+
+        # create the initial mapping of blocks.  Whenever template inheritance
+        # takes place the runtime will update this mapping with the new blocks
+        # from the template.
+        self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
+
+    def super(self, name, current):
+        """Render a parent block."""
+        try:
+            blocks = self.blocks[name]
+            index = blocks.index(current) + 1
+            blocks[index]
+        except LookupError:
+            return self.environment.undefined('there is no parent block '
+                                              'called %r.' % name,
+                                              name='super')
+        return BlockReference(name, self, blocks, index)
+
+    def get(self, key, default=None):
+        """Returns an item from the template context, if it doesn't exist
+        `default` is returned.
+        """
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def resolve(self, key):
+        """Looks up a variable like `__getitem__` or `get` but returns an
+        :class:`Undefined` object with the name of the name looked up.
+        """
+        if key in self.vars:
+            return self.vars[key]
+        if key in self.parent:
+            return self.parent[key]
+        return self.environment.undefined(name=key)
+
+    def get_exported(self):
+        """Get a new dict with the exported variables."""
+        return dict((k, self.vars[k]) for k in self.exported_vars)
+
+    def get_all(self):
+        """Return a copy of the complete context as dict including the
+        exported variables.
+        """
+        return dict(self.parent, **self.vars)
+
+    @internalcode
+    def call(__self, __obj, *args, **kwargs):
+        """Call the callable with the arguments and keyword arguments
+        provided but inject the active context or environment as first
+        argument if the callable is a :func:`contextfunction` or
+        :func:`environmentfunction`.
+        """
+        if __debug__:
+            __traceback_hide__ = True
+        if isinstance(__obj, _context_function_types):
+            if getattr(__obj, 'contextfunction', 0):
+                args = (__self,) + args
+            elif getattr(__obj, 'evalcontextfunction', 0):
+                args = (__self.eval_ctx,) + args
+            elif getattr(__obj, 'environmentfunction', 0):
+                args = (__self.environment,) + args
+        try:
+            return __obj(*args, **kwargs)
+        except StopIteration:
+            return __self.environment.undefined('value was undefined because '
+                                                'a callable raised a '
+                                                'StopIteration exception')
+
+    def derived(self, locals=None):
+        """Internal helper function to create a derived context."""
+        context = new_context(self.environment, self.name, {},
+                              self.parent, True, None, locals)
+        context.eval_ctx = self.eval_ctx
+        context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
+        return context
+
+    def _all(meth):
+        proxy = lambda self: getattr(self.get_all(), meth)()
+        proxy.__doc__ = getattr(dict, meth).__doc__
+        proxy.__name__ = meth
+        return proxy
+
+    keys = _all('keys')
+    values = _all('values')
+    items = _all('items')
+
+    # not available on python 3
+    if hasattr(dict, 'iterkeys'):
+        iterkeys = _all('iterkeys')
+        itervalues = _all('itervalues')
+        iteritems = _all('iteritems')
+    del _all
+
+    def __contains__(self, name):
+        return name in self.vars or name in self.parent
+
+    def __getitem__(self, key):
+        """Lookup a variable or raise `KeyError` if the variable is
+        undefined.
+        """
+        item = self.resolve(key)
+        if isinstance(item, Undefined):
+            raise KeyError(key)
+        return item
+
+    def __repr__(self):
+        return '<%s %s of %r>' % (
+            self.__class__.__name__,
+            repr(self.get_all()),
+            self.name
+        )
+
+
+# register the context as mapping if possible
+try:
+    from collections import Mapping
+    Mapping.register(Context)
+except ImportError:
+    pass
+
+
+class BlockReference(object):
+    """One block on a template reference."""
+
+    def __init__(self, name, context, stack, depth):
+        self.name = name
+        self._context = context
+        self._stack = stack
+        self._depth = depth
+
+    @property
+    def super(self):
+        """Super the block."""
+        if self._depth + 1 >= len(self._stack):
+            return self._context.environment. \
+                undefined('there is no parent block called %r.' %
+                          self.name, name='super')
+        return BlockReference(self.name, self._context, self._stack,
+                              self._depth + 1)
+
+    @internalcode
+    def __call__(self):
+        rv = concat(self._stack[self._depth](self._context))
+        if self._context.eval_ctx.autoescape:
+            rv = Markup(rv)
+        return rv
+
+
+class LoopContext(object):
+    """A loop context for dynamic iteration."""
+
+    def __init__(self, iterable, recurse=None):
+        self._iterator = iter(iterable)
+        self._recurse = recurse
+        self.index0 = -1
+
+        # try to get the length of the iterable early.  This must be done
+        # here because there are some broken iterators around where there
+        # __len__ is the number of iterations left (i'm looking at your
+        # listreverseiterator!).
+        try:
+            self._length = len(iterable)
+        except (TypeError, AttributeError):
+            self._length = None
+
+    def cycle(self, *args):
+        """Cycles among the arguments with the current loop index."""
+        if not args:
+            raise TypeError('no items for cycling given')
+        return args[self.index0 % len(args)]
+
+    first = property(lambda x: x.index0 == 0)
+    last = property(lambda x: x.index0 + 1 == x.length)
+    index = property(lambda x: x.index0 + 1)
+    revindex = property(lambda x: x.length - x.index0)
+    revindex0 = property(lambda x: x.length - x.index)
+
+    def __len__(self):
+        return self.length
+
+    def __iter__(self):
+        return LoopContextIterator(self)
+
+    @internalcode
+    def loop(self, iterable):
+        if self._recurse is None:
+            raise TypeError('Tried to call non recursive loop.  Maybe you '
+                            "forgot the 'recursive' modifier.")
+        return self._recurse(iterable, self._recurse)
+
+    # a nifty trick to enhance the error message if someone tried to call
+    # the the loop without or with too many arguments.
+    __call__ = loop
+    del loop
+
+    @property
+    def length(self):
+        if self._length is None:
+            # if was not possible to get the length of the iterator when
+            # the loop context was created (ie: iterating over a generator)
+            # we have to convert the iterable into a sequence and use the
+            # length of that.
+            iterable = tuple(self._iterator)
+            self._iterator = iter(iterable)
+            self._length = len(iterable) + self.index0 + 1
+        return self._length
+
+    def __repr__(self):
+        return '<%s %r/%r>' % (
+            self.__class__.__name__,
+            self.index,
+            self.length
+        )
+
+
+class LoopContextIterator(object):
+    """The iterator for a loop context."""
+    __slots__ = ('context',)
+
+    def __init__(self, context):
+        self.context = context
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        ctx = self.context
+        ctx.index0 += 1
+        return next(ctx._iterator), ctx
+
+
+class Macro(object):
+    """Wraps a macro function."""
+
+    def __init__(self, environment, func, name, arguments, defaults,
+                 catch_kwargs, catch_varargs, caller):
+        self._environment = environment
+        self._func = func
+        self._argument_count = len(arguments)
+        self.name = name
+        self.arguments = arguments
+        self.defaults = defaults
+        self.catch_kwargs = catch_kwargs
+        self.catch_varargs = catch_varargs
+        self.caller = caller
+
+    @internalcode
+    def __call__(self, *args, **kwargs):
+        # try to consume the positional arguments
+        arguments = list(args[:self._argument_count])
+        off = len(arguments)
+
+        # if the number of arguments consumed is not the number of
+        # arguments expected we start filling in keyword arguments
+        # and defaults.
+        if off != self._argument_count:
+            for idx, name in enumerate(self.arguments[len(arguments):]):
+                try:
+                    value = kwargs.pop(name)
+                except KeyError:
+                    try:
+                        value = self.defaults[idx - self._argument_count + off]
+                    except IndexError:
+                        value = self._environment.undefined(
+                            'parameter %r was not provided' % name, name=name)
+                arguments.append(value)
+
+        # it's important that the order of these arguments does not change
+        # if not also changed in the compiler's `function_scoping` method.
+        # the order is caller, keyword arguments, positional arguments!
+        if self.caller:
+            caller = kwargs.pop('caller', None)
+            if caller is None:
+                caller = self._environment.undefined('No caller defined',
+                                                     name='caller')
+            arguments.append(caller)
+        if self.catch_kwargs:
+            arguments.append(kwargs)
+        elif kwargs:
+            raise TypeError('macro %r takes no keyword argument %r' %
+                            (self.name, next(iter(kwargs))))
+        if self.catch_varargs:
+            arguments.append(args[self._argument_count:])
+        elif len(args) > self._argument_count:
+            raise TypeError('macro %r takes not more than %d argument(s)' %
+                            (self.name, len(self.arguments)))
+        return self._func(*arguments)
+
+    def __repr__(self):
+        return '<%s %s>' % (
+            self.__class__.__name__,
+            self.name is None and 'anonymous' or repr(self.name)
+        )
+
+
+class Undefined(object):
+    """The default undefined type.  This undefined type can be printed and
+    iterated over, but every other access will raise an :exc:`UndefinedError`:
+
+    >>> foo = Undefined(name='foo')
+    >>> str(foo)
+    ''
+    >>> not foo
+    True
+    >>> foo + 42
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    """
+    __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
+                 '_undefined_exception')
+
+    def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
+        self._undefined_hint = hint
+        self._undefined_obj = obj
+        self._undefined_name = name
+        self._undefined_exception = exc
+
+    @internalcode
+    def _fail_with_undefined_error(self, *args, **kwargs):
+        """Regular callback function for undefined objects that raises an
+        `UndefinedError` on call.
+        """
+        if self._undefined_hint is None:
+            if self._undefined_obj is missing:
+                hint = '%r is undefined' % self._undefined_name
+            elif not isinstance(self._undefined_name, basestring):
+                hint = '%s has no element %r' % (
+                    object_type_repr(self._undefined_obj),
+                    self._undefined_name
+                )
+            else:
+                hint = '%r has no attribute %r' % (
+                    object_type_repr(self._undefined_obj),
+                    self._undefined_name
+                )
+        else:
+            hint = self._undefined_hint
+        raise self._undefined_exception(hint)
+
+    __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
+    __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
+    __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
+    __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
+    __int__ = __float__ = __complex__ = __pow__ = __rpow__ = \
+        _fail_with_undefined_error
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        return u''
+
+    def __len__(self):
+        return 0
+
+    def __iter__(self):
+        if 0:
+            yield None
+
+    def __nonzero__(self):
+        return False
+
+    def __repr__(self):
+        return 'Undefined'
+
+
+class DebugUndefined(Undefined):
+    """An undefined that returns the debug info when printed.
+
+    >>> foo = DebugUndefined(name='foo')
+    >>> str(foo)
+    '{{ foo }}'
+    >>> not foo
+    True
+    >>> foo + 42
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    """
+    __slots__ = ()
+
+    def __unicode__(self):
+        if self._undefined_hint is None:
+            if self._undefined_obj is missing:
+                return u'{{ %s }}' % self._undefined_name
+            return '{{ no such element: %s[%r] }}' % (
+                object_type_repr(self._undefined_obj),
+                self._undefined_name
+            )
+        return u'{{ undefined value printed: %s }}' % self._undefined_hint
+
+
+class StrictUndefined(Undefined):
+    """An undefined that barks on print and iteration as well as boolean
+    tests and all kinds of comparisons.  In other words: you can do nothing
+    with it except checking if it's defined using the `defined` test.
+
+    >>> foo = StrictUndefined(name='foo')
+    >>> str(foo)
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    >>> not foo
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    >>> foo + 42
+    Traceback (most recent call last):
+      ...
+    UndefinedError: 'foo' is undefined
+    """
+    __slots__ = ()
+    __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
+        __ne__ = __bool__ = Undefined._fail_with_undefined_error
+
+
+# remove remaining slots attributes, after the metaclass did the magic they
+# are unneeded and irritating as they contain wrong data for the subclasses.
+del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__


[44/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py
new file mode 100644
index 0000000..69ff4bc
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/lexnparse.py
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.lexnparse
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    All the unittests regarding lexing, parsing and syntax.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import time
+import tempfile
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment, Template, TemplateSyntaxError, \
+     UndefinedError, nodes
+
+env = Environment()
+
+
+# how does a string look like in jinja syntax?
+if sys.version_info < (3, 0):
+    def jinja_string_repr(string):
+        return repr(string)[1:]
+else:
+    jinja_string_repr = repr
+
+
+class LexerTestCase(JinjaTestCase):
+
+    def test_raw1(self):
+        tmpl = env.from_string('{% raw %}foo{% endraw %}|'
+                               '{%raw%}{{ bar }}|{% baz %}{%       endraw    %}')
+        assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
+
+    def test_raw2(self):
+        tmpl = env.from_string('1  {%- raw -%}   2   {%- endraw -%}   3')
+        assert tmpl.render() == '123'
+
+    def test_balancing(self):
+        env = Environment('{%', '%}', '${', '}')
+        tmpl = env.from_string('''{% for item in seq
+            %}${{'foo': item}|upper}{% endfor %}''')
+        assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
+
+    def test_comments(self):
+        env = Environment('<!--', '-->', '{', '}')
+        tmpl = env.from_string('''\
+<ul>
+<!--- for item in seq -->
+  <li>{item}</li>
+<!--- endfor -->
+</ul>''')
+        assert tmpl.render(seq=range(3)) == ("<ul>\n  <li>0</li>\n  "
+                                             "<li>1</li>\n  <li>2</li>\n</ul>")
+
+    def test_string_escapes(self):
+        for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
+            tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
+            assert tmpl.render() == char
+        assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
+
+    def test_bytefallback(self):
+        from pprint import pformat
+        tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
+        assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
+
+    def test_operators(self):
+        from ambari_jinja2.lexer import operators
+        for test, expect in operators.iteritems():
+            if test in '([{}])':
+                continue
+            stream = env.lexer.tokenize('{{ %s }}' % test)
+            stream.next()
+            assert stream.current.type == expect
+
+    def test_normalizing(self):
+        for seq in '\r', '\r\n', '\n':
+            env = Environment(newline_sequence=seq)
+            tmpl = env.from_string('1\n2\r\n3\n4\n')
+            result = tmpl.render()
+            assert result.replace(seq, 'X') == '1X2X3X4'
+
+
+class ParserTestCase(JinjaTestCase):
+
+    def test_php_syntax(self):
+        env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
+        tmpl = env.from_string('''\
+<!-- I'm a comment, I'm not interesting -->\
+<? for item in seq -?>
+    <?= item ?>
+<?- endfor ?>''')
+        assert tmpl.render(seq=range(5)) == '01234'
+
+    def test_erb_syntax(self):
+        env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
+        tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>\
+<% for item in seq -%>
+    <%= item %>
+<%- endfor %>''')
+        assert tmpl.render(seq=range(5)) == '01234'
+
+    def test_comment_syntax(self):
+        env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
+        tmpl = env.from_string('''\
+<!--# I'm a comment, I'm not interesting -->\
+<!-- for item in seq --->
+    ${item}
+<!--- endfor -->''')
+        assert tmpl.render(seq=range(5)) == '01234'
+
+    def test_balancing(self):
+        tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
+        assert tmpl.render() == 'bar'
+
+    def test_start_comment(self):
+        tmpl = env.from_string('''{# foo comment
+and bar comment #}
+{% macro blub() %}foo{% endmacro %}
+{{ blub() }}''')
+        assert tmpl.render().strip() == 'foo'
+
+    def test_line_syntax(self):
+        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
+        tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+    ${item}
+% endfor''')
+        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
+               range(5)
+
+        env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
+        tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+    ${item} ## the rest of the stuff
+% endfor''')
+        assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
+                range(5)
+
+    def test_line_syntax_priority(self):
+        # XXX: why is the whitespace there in front of the newline?
+        env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
+        tmpl = env.from_string('''\
+/* ignore me.
+   I'm a multiline comment */
+## for item in seq:
+* ${item}          # this is just extra stuff
+## endfor''')
+        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2'
+        env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##')
+        tmpl = env.from_string('''\
+/* ignore me.
+   I'm a multiline comment */
+# for item in seq:
+* ${item}          ## this is just extra stuff
+    ## extra stuff i just want to ignore
+# endfor''')
+        assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
+
+    def test_error_messages(self):
+        def assert_error(code, expected):
+            try:
+                Template(code)
+            except TemplateSyntaxError, e:
+                assert str(e) == expected, 'unexpected error message'
+            else:
+                assert False, 'that was suposed to be an error'
+
+        assert_error('{% for item in seq %}...{% endif %}',
+                     "Encountered unknown tag 'endif'. Jinja was looking "
+                     "for the following tags: 'endfor' or 'else'. The "
+                     "innermost block that needs to be closed is 'for'.")
+        assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
+                     "Encountered unknown tag 'endfor'. Jinja was looking for "
+                     "the following tags: 'elif' or 'else' or 'endif'. The "
+                     "innermost block that needs to be closed is 'if'.")
+        assert_error('{% if foo %}',
+                     "Unexpected end of template. Jinja was looking for the "
+                     "following tags: 'elif' or 'else' or 'endif'. The "
+                     "innermost block that needs to be closed is 'if'.")
+        assert_error('{% for item in seq %}',
+                     "Unexpected end of template. Jinja was looking for the "
+                     "following tags: 'endfor' or 'else'. The innermost block "
+                     "that needs to be closed is 'for'.")
+        assert_error('{% block foo-bar-baz %}',
+                     "Block names in Jinja have to be valid Python identifiers "
+                     "and may not contain hypens, use an underscore instead.")
+        assert_error('{% unknown_tag %}',
+                     "Encountered unknown tag 'unknown_tag'.")
+
+
+class SyntaxTestCase(JinjaTestCase):
+
+    def test_call(self):
+        env = Environment()
+        env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
+        tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
+        assert tmpl.render() == 'abdfh'
+
+    def test_slicing(self):
+        tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
+        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+    def test_attr(self):
+        tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
+        assert tmpl.render(foo={'bar': 42}) == '42|42'
+
+    def test_subscript(self):
+        tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
+        assert tmpl.render(foo=[0, 1, 2]) == '0|2'
+
+    def test_tuple(self):
+        tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
+        assert tmpl.render() == '()|(1,)|(1, 2)'
+
+    def test_math(self):
+        tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
+        assert tmpl.render() == '1.5|8'
+
+    def test_div(self):
+        tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
+        assert tmpl.render() == '1|1.5|1'
+
+    def test_unary(self):
+        tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
+        assert tmpl.render() == '3|-3'
+
+    def test_concat(self):
+        tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
+        assert tmpl.render() == '[1, 2]foo'
+
+    def test_compare(self):
+        tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
+                               '{{ 2 == 2 }}|{{ 1 <= 1 }}')
+        assert tmpl.render() == 'True|True|True|True|True'
+
+    def test_inop(self):
+        tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
+        assert tmpl.render() == 'True|False'
+
+    def test_literals(self):
+        tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
+        assert tmpl.render().lower() == '[]|{}|()'
+
+    def test_bool(self):
+        tmpl = env.from_string('{{ true and false }}|{{ false '
+                               'or true }}|{{ not false }}')
+        assert tmpl.render() == 'False|True|True'
+
+    def test_grouping(self):
+        tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
+        assert tmpl.render() == 'False'
+
+    def test_django_attr(self):
+        tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
+        assert tmpl.render() == '1|1'
+
+    def test_conditional_expression(self):
+        tmpl = env.from_string('''{{ 0 if true else 1 }}''')
+        assert tmpl.render() == '0'
+
+    def test_short_conditional_expression(self):
+        tmpl = env.from_string('<{{ 1 if false }}>')
+        assert tmpl.render() == '<>'
+
+        tmpl = env.from_string('<{{ (1 if false).bar }}>')
+        self.assert_raises(UndefinedError, tmpl.render)
+
+    def test_filter_priority(self):
+        tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
+        assert tmpl.render() == 'FOOBAR'
+
+    def test_function_calls(self):
+        tests = [
+            (True, '*foo, bar'),
+            (True, '*foo, *bar'),
+            (True, '*foo, bar=42'),
+            (True, '**foo, *bar'),
+            (True, '**foo, bar'),
+            (False, 'foo, bar'),
+            (False, 'foo, bar=42'),
+            (False, 'foo, bar=23, *args'),
+            (False, 'a, b=c, *d, **e'),
+            (False, '*foo, **bar')
+        ]
+        for should_fail, sig in tests:
+            if should_fail:
+                self.assert_raises(TemplateSyntaxError,
+                    env.from_string, '{{ foo(%s) }}' % sig)
+            else:
+                env.from_string('foo(%s)' % sig)
+
+    def test_tuple_expr(self):
+        for tmpl in [
+            '{{ () }}',
+            '{{ (1, 2) }}',
+            '{{ (1, 2,) }}',
+            '{{ 1, }}',
+            '{{ 1, 2 }}',
+            '{% for foo, bar in seq %}...{% endfor %}',
+            '{% for x in foo, bar %}...{% endfor %}',
+            '{% for x in foo, %}...{% endfor %}'
+        ]:
+            assert env.from_string(tmpl)
+
+    def test_trailing_comma(self):
+        tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
+        assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
+
+    def test_block_end_name(self):
+        env.from_string('{% block foo %}...{% endblock foo %}')
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '{% block x %}{% endblock y %}')
+
+    def test_contant_casing(self):
+        for const in True, False, None:
+            tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
+                str(const), str(const).lower(), str(const).upper()
+            ))
+            assert tmpl.render() == '%s|%s|' % (const, const)
+
+    def test_test_chaining(self):
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '{{ foo is string is sequence }}')
+        env.from_string('{{ 42 is string or 42 is number }}'
+            ).render() == 'True'
+
+    def test_string_concatenation(self):
+        tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
+        assert tmpl.render() == 'foobarbaz'
+
+    def test_notin(self):
+        bar = xrange(100)
+        tmpl = env.from_string('''{{ not 42 in bar }}''')
+        assert tmpl.render(bar=bar) == unicode(not 42 in bar)
+
+    def test_implicit_subscribed_tuple(self):
+        class Foo(object):
+            def __getitem__(self, x):
+                return x
+        t = env.from_string('{{ foo[1, 2] }}')
+        assert t.render(foo=Foo()) == u'(1, 2)'
+
+    def test_raw2(self):
+        tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
+        assert tmpl.render() == '{{ FOO }} and {% BAR %}'
+
+    def test_const(self):
+        tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
+                               '{{ none is defined }}|{{ missing is defined }}')
+        assert tmpl.render() == 'True|False|None|True|False'
+
+    def test_neg_filter_priority(self):
+        node = env.parse('{{ -1|foo }}')
+        assert isinstance(node.body[0].nodes[0], nodes.Filter)
+        assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
+
+    def test_const_assign(self):
+        constass1 = '''{% set true = 42 %}'''
+        constass2 = '''{% for none in seq %}{% endfor %}'''
+        for tmpl in constass1, constass2:
+            self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
+
+    def test_localset(self):
+        tmpl = env.from_string('''{% set foo = 0 %}\
+{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
+{{ foo }}''')
+        assert tmpl.render() == '0'
+
+    def test_parse_unary(self):
+        tmpl = env.from_string('{{ -foo["bar"] }}')
+        assert tmpl.render(foo={'bar': 42}) == '-42'
+        tmpl = env.from_string('{{ -foo["bar"]|abs }}')
+        assert tmpl.render(foo={'bar': 42}) == '42'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(LexerTestCase))
+    suite.addTest(unittest.makeSuite(ParserTestCase))
+    suite.addTest(unittest.makeSuite(SyntaxTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py
new file mode 100644
index 0000000..e133bd4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/loader.py
@@ -0,0 +1,191 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.loader
+    ~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test the loaders.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import time
+import tempfile
+import shutil
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase, dict_loader, \
+     package_loader, filesystem_loader, function_loader, \
+     choice_loader, prefix_loader
+
+from ambari_jinja2 import Environment, loaders
+from ambari_jinja2.loaders import split_template_path
+from ambari_jinja2.exceptions import TemplateNotFound
+
+
+class LoaderTestCase(JinjaTestCase):
+
+    def test_dict_loader(self):
+        env = Environment(loader=dict_loader)
+        tmpl = env.get_template('justdict.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_package_loader(self):
+        env = Environment(loader=package_loader)
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_filesystem_loader(self):
+        env = Environment(loader=filesystem_loader)
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        tmpl = env.get_template('foo/test.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_choice_loader(self):
+        env = Environment(loader=choice_loader)
+        tmpl = env.get_template('justdict.html')
+        assert tmpl.render().strip() == 'FOO'
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_function_loader(self):
+        env = Environment(loader=function_loader)
+        tmpl = env.get_template('justfunction.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+    def test_prefix_loader(self):
+        env = Environment(loader=prefix_loader)
+        tmpl = env.get_template('a/test.html')
+        assert tmpl.render().strip() == 'BAR'
+        tmpl = env.get_template('b/justdict.html')
+        assert tmpl.render().strip() == 'FOO'
+        self.assert_raises(TemplateNotFound, env.get_template, 'missing')
+
+    def test_caching(self):
+        changed = False
+        class TestLoader(loaders.BaseLoader):
+            def get_source(self, environment, template):
+                return u'foo', None, lambda: not changed
+        env = Environment(loader=TestLoader(), cache_size=-1)
+        tmpl = env.get_template('template')
+        assert tmpl is env.get_template('template')
+        changed = True
+        assert tmpl is not env.get_template('template')
+        changed = False
+
+        env = Environment(loader=TestLoader(), cache_size=0)
+        assert env.get_template('template') \
+               is not env.get_template('template')
+
+        env = Environment(loader=TestLoader(), cache_size=2)
+        t1 = env.get_template('one')
+        t2 = env.get_template('two')
+        assert t2 is env.get_template('two')
+        assert t1 is env.get_template('one')
+        t3 = env.get_template('three')
+        assert 'one' in env.cache
+        assert 'two' not in env.cache
+        assert 'three' in env.cache
+
+    def test_split_template_path(self):
+        assert split_template_path('foo/bar') == ['foo', 'bar']
+        assert split_template_path('./foo/bar') == ['foo', 'bar']
+        self.assert_raises(TemplateNotFound, split_template_path, '../foo')
+
+
+class ModuleLoaderTestCase(JinjaTestCase):
+    archive = None
+
+    def compile_down(self, zip='deflated', py_compile=False):
+        super(ModuleLoaderTestCase, self).setup()
+        log = []
+        self.reg_env = Environment(loader=prefix_loader)
+        if zip is not None:
+            self.archive = tempfile.mkstemp(suffix='.zip')[1]
+        else:
+            self.archive = tempfile.mkdtemp()
+        self.reg_env.compile_templates(self.archive, zip=zip,
+                                       log_function=log.append,
+                                       py_compile=py_compile)
+        self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
+        return ''.join(log)
+
+    def teardown(self):
+        super(ModuleLoaderTestCase, self).teardown()
+        if hasattr(self, 'mod_env'):
+            if os.path.isfile(self.archive):
+                os.remove(self.archive)
+            else:
+                shutil.rmtree(self.archive)
+            self.archive = None
+
+    def test_log(self):
+        log = self.compile_down()
+        assert 'Compiled "a/foo/test.html" as ' \
+               'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
+        assert 'Finished compiling templates' in log
+        assert 'Could not compile "a/syntaxerror.html": ' \
+               'Encountered unknown tag \'endif\'' in log
+
+    def _test_common(self):
+        tmpl1 = self.reg_env.get_template('a/test.html')
+        tmpl2 = self.mod_env.get_template('a/test.html')
+        assert tmpl1.render() == tmpl2.render()
+
+        tmpl1 = self.reg_env.get_template('b/justdict.html')
+        tmpl2 = self.mod_env.get_template('b/justdict.html')
+        assert tmpl1.render() == tmpl2.render()
+
+    def test_deflated_zip_compile(self):
+        self.compile_down(zip='deflated')
+        self._test_common()
+
+    def test_stored_zip_compile(self):
+        self.compile_down(zip='stored')
+        self._test_common()
+
+    def test_filesystem_compile(self):
+        self.compile_down(zip=None)
+        self._test_common()
+
+    def test_weak_references(self):
+        self.compile_down()
+        tmpl = self.mod_env.get_template('a/test.html')
+        key = loaders.ModuleLoader.get_template_key('a/test.html')
+        name = self.mod_env.loader.module.__name__
+
+        assert hasattr(self.mod_env.loader.module, key)
+        assert name in sys.modules
+
+        # unset all, ensure the module is gone from sys.modules
+        self.mod_env = tmpl = None
+
+        try:
+            import gc
+            gc.collect()
+        except:
+            pass
+
+        assert name not in sys.modules
+
+    def test_byte_compilation(self):
+        log = self.compile_down(py_compile=True)
+        assert 'Byte-compiled "a/test.html"' in log
+        tmpl1 = self.mod_env.get_template('a/test.html')
+        mod = self.mod_env.loader.module. \
+            tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
+        assert mod.__file__.endswith('.pyc')
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(LoaderTestCase))
+    suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py
new file mode 100644
index 0000000..b457df2
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/regression.py
@@ -0,0 +1,258 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.regression
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests corner cases and bugs.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
+     TemplateNotFound, PrefixLoader
+
+env = Environment()
+
+
+class CornerTestCase(JinjaTestCase):
+
+    def test_assigned_scoping(self):
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) -%}
+            [{{ item }}]
+        {%- endfor %}
+        {{- item -}}
+        ''')
+        assert t.render(item=42) == '[1][2][3][4]42'
+
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) -%}
+            [{{ item }}]
+        {%- endfor %}
+        {%- set item = 42 %}
+        {{- item -}}
+        ''')
+        assert t.render() == '[1][2][3][4]42'
+
+        t = env.from_string('''
+        {%- set item = 42 %}
+        {%- for item in (1, 2, 3, 4) -%}
+            [{{ item }}]
+        {%- endfor %}
+        {{- item -}}
+        ''')
+        assert t.render() == '[1][2][3][4]42'
+
+    def test_closure_scoping(self):
+        t = env.from_string('''
+        {%- set wrapper = "<FOO>" %}
+        {%- for item in (1, 2, 3, 4) %}
+            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+            {{- wrapper() }}
+        {%- endfor %}
+        {{- wrapper -}}
+        ''')
+        assert t.render() == '[1][2][3][4]<FOO>'
+
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) %}
+            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+            {{- wrapper() }}
+        {%- endfor %}
+        {%- set wrapper = "<FOO>" %}
+        {{- wrapper -}}
+        ''')
+        assert t.render() == '[1][2][3][4]<FOO>'
+
+        t = env.from_string('''
+        {%- for item in (1, 2, 3, 4) %}
+            {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+            {{- wrapper() }}
+        {%- endfor %}
+        {{- wrapper -}}
+        ''')
+        assert t.render(wrapper=23) == '[1][2][3][4]23'
+
+
+class BugTestCase(JinjaTestCase):
+
+    def test_keyword_folding(self):
+        env = Environment()
+        env.filters['testing'] = lambda value, some: value + some
+        assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
+               .render() == 'teststuff'
+
+    def test_extends_output_bugs(self):
+        env = Environment(loader=DictLoader({
+            'parent.html': '(({% block title %}{% endblock %}))'
+        }))
+
+        t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
+                            '[[{% block title %}title{% endblock %}]]'
+                            '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
+        assert t.render(expr=False) == '[[title]](1)(2)(3)'
+        assert t.render(expr=True) == '((title))'
+
+    def test_urlize_filter_escaping(self):
+        tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
+        assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">http://www.example.org/&lt;foo</a>'
+
+    def test_loop_call_loop(self):
+        tmpl = env.from_string('''
+
+        {% macro test() %}
+            {{ caller() }}
+        {% endmacro %}
+
+        {% for num1 in range(5) %}
+            {% call test() %}
+                {% for num2 in range(10) %}
+                    {{ loop.index }}
+                {% endfor %}
+            {% endcall %}
+        {% endfor %}
+
+        ''')
+
+        assert tmpl.render().split() == map(unicode, range(1, 11)) * 5
+
+    def test_weird_inline_comment(self):
+        env = Environment(line_statement_prefix='%')
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '% for item in seq {# missing #}\n...% endfor')
+
+    def test_old_macro_loop_scoping_bug(self):
+        tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
+                               '{% macro i() %}3{% endmacro %}{{ i() }}')
+        assert tmpl.render() == '123'
+
+    def test_partial_conditional_assignments(self):
+        tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
+        assert tmpl.render(a=23) == '23'
+        assert tmpl.render(b=True) == '42'
+
+    def test_stacked_locals_scoping_bug(self):
+        env = Environment(line_statement_prefix='#')
+        t = env.from_string('''\
+# for j in [1, 2]:
+#   set x = 1
+#   for i in [1, 2]:
+#     print x
+#     if i % 2 == 0:
+#       set x = x + 1
+#     endif
+#   endfor
+# endfor
+# if a
+#   print 'A'
+# elif b
+#   print 'B'
+# elif c == d
+#   print 'C'
+# else
+#   print 'D'
+# endif
+    ''')
+        assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
+
+    def test_stacked_locals_scoping_bug_twoframe(self):
+        t = Template('''
+            {% set x = 1 %}
+            {% for item in foo %}
+                {% if item == 1 %}
+                    {% set x = 2 %}
+                {% endif %}
+            {% endfor %}
+            {{ x }}
+        ''')
+        rv = t.render(foo=[1]).strip()
+        assert rv == u'1'
+
+    def test_call_with_args(self):
+        t = Template("""{% macro dump_users(users) -%}
+        <ul>
+          {%- for user in users -%}
+            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+          {%- endfor -%}
+          </ul>
+        {%- endmacro -%}
+
+        {% call(user) dump_users(list_of_user) -%}
+          <dl>
+            <dl>Realname</dl>
+            <dd>{{ user.realname|e }}</dd>
+            <dl>Description</dl>
+            <dd>{{ user.description }}</dd>
+          </dl>
+        {% endcall %}""")
+
+        assert [x.strip() for x in t.render(list_of_user=[{
+            'username':'apo',
+            'realname':'something else',
+            'description':'test'
+        }]).splitlines()] == [
+            u'<ul><li><p>apo</p><dl>',
+            u'<dl>Realname</dl>',
+            u'<dd>something else</dd>',
+            u'<dl>Description</dl>',
+            u'<dd>test</dd>',
+            u'</dl>',
+            u'</li></ul>'
+        ]
+
+    def test_empty_if_condition_fails(self):
+        self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
+        self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
+        self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
+
+    def test_recursive_loop_bug(self):
+        tpl1 = Template("""
+        {% for p in foo recursive%}
+            {{p.bar}}
+            {% for f in p.fields recursive%}
+                {{f.baz}}
+                {{p.bar}}
+                {% if f.rec %}
+                    {{ loop(f.sub) }}
+                {% endif %}
+            {% endfor %}
+        {% endfor %}
+        """)
+
+        tpl2 = Template("""
+        {% for p in foo%}
+            {{p.bar}}
+            {% for f in p.fields recursive%}
+                {{f.baz}}
+                {{p.bar}}
+                {% if f.rec %}
+                    {{ loop(f.sub) }}
+                {% endif %}
+            {% endfor %}
+        {% endfor %}
+        """)
+
+    def test_correct_prefix_loader_name(self):
+        env = Environment(loader=PrefixLoader({
+            'foo':  DictLoader({})
+        }))
+        try:
+            env.get_template('foo/bar.html')
+        except TemplateNotFound, e:
+            assert e.name == 'foo/bar.html'
+        else:
+            assert False, 'expected error here'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(CornerTestCase))
+    suite.addTest(unittest.makeSuite(BugTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html
new file mode 100644
index 0000000..77669fa
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/broken.html
@@ -0,0 +1,3 @@
+Before
+{{ fail() }}
+After

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html
new file mode 100644
index 0000000..b7d6715
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/foo/test.html
@@ -0,0 +1 @@
+FOO

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html
new file mode 100644
index 0000000..f21b817
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/syntaxerror.html
@@ -0,0 +1,4 @@
+Foo
+{% for item in broken %}
+  ...
+{% endif %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html
new file mode 100644
index 0000000..ba578e4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/res/templates/test.html
@@ -0,0 +1 @@
+BAR

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py
new file mode 100644
index 0000000..893526d
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/security.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.security
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Checks the sandbox and other security features.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment
+from ambari_jinja2.sandbox import SandboxedEnvironment, \
+     ImmutableSandboxedEnvironment, unsafe
+from ambari_jinja2 import Markup, escape
+from ambari_jinja2.exceptions import SecurityError, TemplateSyntaxError
+
+
+class PrivateStuff(object):
+
+    def bar(self):
+        return 23
+
+    @unsafe
+    def foo(self):
+        return 42
+
+    def __repr__(self):
+        return 'PrivateStuff'
+
+
+class PublicStuff(object):
+    bar = lambda self: 23
+    _foo = lambda self: 42
+
+    def __repr__(self):
+        return 'PublicStuff'
+
+
+class SandboxTestCase(JinjaTestCase):
+
+    def test_unsafe(self):
+        env = SandboxedEnvironment()
+        self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
+                           foo=PrivateStuff())
+        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
+
+        self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
+                           foo=PublicStuff())
+        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
+        self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
+        self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
+        self.assert_raises(SecurityError, env.from_string(
+            "{{ foo.__class__.__subclasses__() }}").render, foo=42)
+
+    def test_immutable_environment(self):
+        env = ImmutableSandboxedEnvironment()
+        self.assert_raises(SecurityError, env.from_string(
+            '{{ [].append(23) }}').render)
+        self.assert_raises(SecurityError, env.from_string(
+            '{{ {1:2}.clear() }}').render)
+
+    def test_restricted(self):
+        env = SandboxedEnvironment()
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                      "{% for item.attribute in seq %}...{% endfor %}")
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                      "{% for foo, bar.baz in seq %}...{% endfor %}")
+
+    def test_markup_operations(self):
+        # adding two strings should escape the unsafe one
+        unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+        safe = Markup('<em>username</em>')
+        assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
+
+        # string interpolations are safe to use too
+        assert Markup('<em>%s</em>') % '<bad user>' == \
+               '<em>&lt;bad user&gt;</em>'
+        assert Markup('<em>%(username)s</em>') % {
+            'username': '<bad user>'
+        } == '<em>&lt;bad user&gt;</em>'
+
+        # an escaped object is markup too
+        assert type(Markup('foo') + 'bar') is Markup
+
+        # and it implements __html__ by returning itself
+        x = Markup("foo")
+        assert x.__html__() is x
+
+        # it also knows how to treat __html__ objects
+        class Foo(object):
+            def __html__(self):
+                return '<em>awesome</em>'
+            def __unicode__(self):
+                return 'awesome'
+        assert Markup(Foo()) == '<em>awesome</em>'
+        assert Markup('<strong>%s</strong>') % Foo() == \
+               '<strong><em>awesome</em></strong>'
+
+        # escaping and unescaping
+        assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+        assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+        assert Markup("&lt;test&gt;").unescape() == "<test>"
+
+
+    def test_template_data(self):
+        env = Environment(autoescape=True)
+        t = env.from_string('{% macro say_hello(name) %}'
+                            '<p>Hello {{ name }}!</p>{% endmacro %}'
+                            '{{ say_hello("<blink>foo</blink>") }}')
+        escaped_out = '<p>Hello &lt;blink&gt;foo&lt;/blink&gt;!</p>'
+        assert t.render() == escaped_out
+        assert unicode(t.module) == escaped_out
+        assert escape(t.module) == escaped_out
+        assert t.module.say_hello('<blink>foo</blink>') == escaped_out
+        assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
+
+
+    def test_attr_filter(self):
+        env = SandboxedEnvironment()
+        tmpl = env.from_string('{{ 42|attr("__class__")|attr("__subclasses__")() }}')
+        self.assert_raises(SecurityError, tmpl.render)
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(SandboxTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py
new file mode 100644
index 0000000..2f7b792
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/tests.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.tests
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Who tests the tests?
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import unittest
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Markup, Environment
+
+env = Environment()
+
+
+class TestsTestCase(JinjaTestCase):
+
+    def test_defined(self):
+        tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
+        assert tmpl.render() == 'False|True'
+
+    def test_even(self):
+        tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
+        assert tmpl.render() == 'False|True'
+
+    def test_odd(self):
+        tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
+        assert tmpl.render() == 'True|False'
+
+    def test_lower(self):
+        tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
+        assert tmpl.render() == 'True|False'
+
+    def test_typechecks(self):
+        tmpl = env.from_string('''
+            {{ 42 is undefined }}
+            {{ 42 is defined }}
+            {{ 42 is none }}
+            {{ none is none }}
+            {{ 42 is number }}
+            {{ 42 is string }}
+            {{ "foo" is string }}
+            {{ "foo" is sequence }}
+            {{ [1] is sequence }}
+            {{ range is callable }}
+            {{ 42 is callable }}
+            {{ range(5) is iterable }}
+        ''')
+        assert tmpl.render().split() == [
+            'False', 'True', 'False', 'True', 'True', 'False',
+            'True', 'True', 'True', 'True', 'False', 'True'
+        ]
+
+    def test_sequence(self):
+        tmpl = env.from_string(
+            '{{ [1, 2, 3] is sequence }}|'
+            '{{ "foo" is sequence }}|'
+            '{{ 42 is sequence }}'
+        )
+        assert tmpl.render() == 'True|True|False'
+
+    def test_upper(self):
+        tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
+        assert tmpl.render() == 'True|False'
+
+    def test_sameas(self):
+        tmpl = env.from_string('{{ foo is sameas false }}|'
+                               '{{ 0 is sameas false }}')
+        assert tmpl.render(foo=False) == 'True|False'
+
+    def test_no_paren_for_arg1(self):
+        tmpl = env.from_string('{{ foo is sameas none }}')
+        assert tmpl.render(foo=None) == 'True'
+
+    def test_escaped(self):
+        env = Environment(autoescape=True)
+        tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
+        assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(TestsTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py
new file mode 100644
index 0000000..297ba6a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/utils.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.utils
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests utilities jinja uses.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import gc
+import unittest
+
+import pickle
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment, Undefined, DebugUndefined, \
+     StrictUndefined, UndefinedError, Template, meta
+from ambari_jinja2.utils import LRUCache, escape, object_type_repr
+
+
+class LRUCacheTestCase(JinjaTestCase):
+
+    def test_simple(self):
+        d = LRUCache(3)
+        d["a"] = 1
+        d["b"] = 2
+        d["c"] = 3
+        d["a"]
+        d["d"] = 4
+        assert len(d) == 3
+        assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d
+
+    def test_pickleable(self):
+        cache = LRUCache(2)
+        cache["foo"] = 42
+        cache["bar"] = 23
+        cache["foo"]
+
+        for protocol in range(3):
+            copy = pickle.loads(pickle.dumps(cache, protocol))
+            assert copy.capacity == cache.capacity
+            assert copy._mapping == cache._mapping
+            assert copy._queue == cache._queue
+
+
+class HelpersTestCase(JinjaTestCase):
+
+    def test_object_type_repr(self):
+        class X(object):
+            pass
+        self.assert_equal(object_type_repr(42), 'int object')
+        self.assert_equal(object_type_repr([]), 'list object')
+        self.assert_equal(object_type_repr(X()),
+                         'ambari_jinja2.testsuite.utils.X object')
+        self.assert_equal(object_type_repr(None), 'None')
+        self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
+
+
+class MarkupLeakTestCase(JinjaTestCase):
+
+    def test_markup_leaks(self):
+        counts = set()
+        for count in xrange(20):
+            for item in xrange(1000):
+                escape("foo")
+                escape("<foo>")
+                escape(u"foo")
+                escape(u"<foo>")
+            counts.add(len(gc.get_objects()))
+        assert len(counts) == 1, 'ouch, c extension seems to leak objects'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(LRUCacheTestCase))
+    suite.addTest(unittest.makeSuite(HelpersTestCase))
+
+    # this test only tests the c extension
+    if not hasattr(escape, 'func_code'):
+        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
+
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py
new file mode 100644
index 0000000..bd3c0b4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/utils.py
@@ -0,0 +1,601 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.utils
+    ~~~~~~~~~~~~
+
+    Utility functions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import sys
+import errno
+try:
+    from thread import allocate_lock
+except ImportError:
+    from dummy_thread import allocate_lock
+from collections import deque
+from itertools import imap
+
+
+_word_split_re = re.compile(r'(\s+)')
+_punctuation_re = re.compile(
+    '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
+        '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
+        '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
+    )
+)
+_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^;]+);')
+_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+_digits = '0123456789'
+
+# special singleton representing missing values for the runtime
+missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
+
+# internal code
+internal_code = set()
+
+
+# concatenate a list of strings and convert them to unicode.
+# unfortunately there is a bug in python 2.4 and lower that causes
+# unicode.join trash the traceback.
+_concat = u''.join
+try:
+    def _test_gen_bug():
+        raise TypeError(_test_gen_bug)
+        yield None
+    _concat(_test_gen_bug())
+except TypeError, _error:
+    if not _error.args or _error.args[0] is not _test_gen_bug:
+        def concat(gen):
+            try:
+                return _concat(list(gen))
+            except:
+                # this hack is needed so that the current frame
+                # does not show up in the traceback.
+                exc_type, exc_value, tb = sys.exc_info()
+                raise exc_type, exc_value, tb.tb_next
+    else:
+        concat = _concat
+    del _test_gen_bug, _error
+
+
+# for python 2.x we create outselves a next() function that does the
+# basics without exception catching.
+try:
+    next = next
+except NameError:
+    def next(x):
+        return x.next()
+
+
+# if this python version is unable to deal with unicode filenames
+# when passed to encode we let this function encode it properly.
+# This is used in a couple of places.  As far as Jinja is concerned
+# filenames are unicode *or* bytestrings in 2.x and unicode only in
+# 3.x because compile cannot handle bytes
+if sys.version_info < (3, 0):
+    def _encode_filename(filename):
+        if isinstance(filename, unicode):
+            return filename.encode('utf-8')
+        return filename
+else:
+    def _encode_filename(filename):
+        assert filename is None or isinstance(filename, str), \
+            'filenames must be strings'
+        return filename
+
+from keyword import iskeyword as is_python_keyword
+
+
+# common types.  These do exist in the special types module too which however
+# does not exist in IronPython out of the box.  Also that way we don't have
+# to deal with implementation specific stuff here
+class _C(object):
+    def method(self): pass
+def _func():
+    yield None
+FunctionType = type(_func)
+GeneratorType = type(_func())
+MethodType = type(_C.method)
+CodeType = type(_C.method.func_code)
+try:
+    raise TypeError()
+except TypeError:
+    _tb = sys.exc_info()[2]
+    TracebackType = type(_tb)
+    FrameType = type(_tb.tb_frame)
+del _C, _tb, _func
+
+
+def contextfunction(f):
+    """This decorator can be used to mark a function or method context callable.
+    A context callable is passed the active :class:`Context` as first argument when
+    called from the template.  This is useful if a function wants to get access
+    to the context or functions provided on the context object.  For example
+    a function that returns a sorted list of template variables the current
+    template exports could look like this::
+
+        @contextfunction
+        def get_exported_names(context):
+            return sorted(context.exported_vars)
+    """
+    f.contextfunction = True
+    return f
+
+
+def evalcontextfunction(f):
+    """This decoraotr can be used to mark a function or method as an eval
+    context callable.  This is similar to the :func:`contextfunction`
+    but instead of passing the context, an evaluation context object is
+    passed.  For more information about the eval context, see
+    :ref:`eval-context`.
+
+    .. versionadded:: 2.4
+    """
+    f.evalcontextfunction = True
+    return f
+
+
+def environmentfunction(f):
+    """This decorator can be used to mark a function or method as environment
+    callable.  This decorator works exactly like the :func:`contextfunction`
+    decorator just that the first argument is the active :class:`Environment`
+    and not context.
+    """
+    f.environmentfunction = True
+    return f
+
+
+def internalcode(f):
+    """Marks the function as internally used"""
+    internal_code.add(f.func_code)
+    return f
+
+
+def is_undefined(obj):
+    """Check if the object passed is undefined.  This does nothing more than
+    performing an instance check against :class:`Undefined` but looks nicer.
+    This can be used for custom filters or tests that want to react to
+    undefined variables.  For example a custom default filter can look like
+    this::
+
+        def default(var, default=''):
+            if is_undefined(var):
+                return default
+            return var
+    """
+    from ambari_jinja2.runtime import Undefined
+    return isinstance(obj, Undefined)
+
+
+def consume(iterable):
+    """Consumes an iterable without doing anything with it."""
+    for event in iterable:
+        pass
+
+
+def clear_caches():
+    """Jinja2 keeps internal caches for environments and lexers.  These are
+    used so that Jinja2 doesn't have to recreate environments and lexers all
+    the time.  Normally you don't have to care about that but if you are
+    messuring memory consumption you may want to clean the caches.
+    """
+    from ambari_jinja2.environment import _spontaneous_environments
+    from ambari_jinja2.lexer import _lexer_cache
+    _spontaneous_environments.clear()
+    _lexer_cache.clear()
+
+
+def import_string(import_name, silent=False):
+    """Imports an object based on a string.  This use useful if you want to
+    use import paths as endpoints or something similar.  An import path can
+    be specified either in dotted notation (``xml.sax.saxutils.escape``)
+    or with a colon as object delimiter (``xml.sax.saxutils:escape``).
+
+    If the `silent` is True the return value will be `None` if the import
+    fails.
+
+    :return: imported object
+    """
+    try:
+        if ':' in import_name:
+            module, obj = import_name.split(':', 1)
+        elif '.' in import_name:
+            items = import_name.split('.')
+            module = '.'.join(items[:-1])
+            obj = items[-1]
+        else:
+            return __import__(import_name)
+        return getattr(__import__(module, None, None, [obj]), obj)
+    except (ImportError, AttributeError):
+        if not silent:
+            raise
+
+
+def open_if_exists(filename, mode='rb'):
+    """Returns a file descriptor for the filename if that file exists,
+    otherwise `None`.
+    """
+    try:
+        return open(filename, mode)
+    except IOError, e:
+        if e.errno not in (errno.ENOENT, errno.EISDIR):
+            raise
+
+
+def object_type_repr(obj):
+    """Returns the name of the object's type.  For some recognized
+    singletons the name of the object is returned instead. (For
+    example for `None` and `Ellipsis`).
+    """
+    if obj is None:
+        return 'None'
+    elif obj is Ellipsis:
+        return 'Ellipsis'
+    # __builtin__ in 2.x, builtins in 3.x
+    if obj.__class__.__module__ in ('__builtin__', 'builtins'):
+        name = obj.__class__.__name__
+    else:
+        name = obj.__class__.__module__ + '.' + obj.__class__.__name__
+    return '%s object' % name
+
+
+def pformat(obj, verbose=False):
+    """Prettyprint an object.  Either use the `pretty` library or the
+    builtin `pprint`.
+    """
+    try:
+        from pretty import pretty
+        return pretty(obj, verbose=verbose)
+    except ImportError:
+        from pprint import pformat
+        return pformat(obj)
+
+
+def urlize(text, trim_url_limit=None, nofollow=False):
+    """Converts any URLs in text into clickable links. Works on http://,
+    https:// and www. links. Links can have trailing punctuation (periods,
+    commas, close-parens) and leading punctuation (opening parens) and
+    it'll still do the right thing.
+
+    If trim_url_limit is not None, the URLs in link text will be limited
+    to trim_url_limit characters.
+
+    If nofollow is True, the URLs in link text will get a rel="nofollow"
+    attribute.
+    """
+    trim_url = lambda x, limit=trim_url_limit: limit is not None \
+                         and (x[:limit] + (len(x) >=limit and '...'
+                         or '')) or x
+    words = _word_split_re.split(unicode(escape(text)))
+    nofollow_attr = nofollow and ' rel="nofollow"' or ''
+    for i, word in enumerate(words):
+        match = _punctuation_re.match(word)
+        if match:
+            lead, middle, trail = match.groups()
+            if middle.startswith('www.') or (
+                '@' not in middle and
+                not middle.startswith('http://') and
+                len(middle) > 0 and
+                middle[0] in _letters + _digits and (
+                    middle.endswith('.org') or
+                    middle.endswith('.net') or
+                    middle.endswith('.com')
+                )):
+                middle = '<a href="http://%s"%s>%s</a>' % (middle,
+                    nofollow_attr, trim_url(middle))
+            if middle.startswith('http://') or \
+               middle.startswith('https://'):
+                middle = '<a href="%s"%s>%s</a>' % (middle,
+                    nofollow_attr, trim_url(middle))
+            if '@' in middle and not middle.startswith('www.') and \
+               not ':' in middle and _simple_email_re.match(middle):
+                middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
+            if lead + middle + trail != word:
+                words[i] = lead + middle + trail
+    return u''.join(words)
+
+
+def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
+    """Generate some lorem impsum for the template."""
+    from ambari_jinja2.constants import LOREM_IPSUM_WORDS
+    from random import choice, randrange
+    words = LOREM_IPSUM_WORDS.split()
+    result = []
+
+    for _ in xrange(n):
+        next_capitalized = True
+        last_comma = last_fullstop = 0
+        word = None
+        last = None
+        p = []
+
+        # each paragraph contains out of 20 to 100 words.
+        for idx, _ in enumerate(xrange(randrange(min, max))):
+            while True:
+                word = choice(words)
+                if word != last:
+                    last = word
+                    break
+            if next_capitalized:
+                word = word.capitalize()
+                next_capitalized = False
+            # add commas
+            if idx - randrange(3, 8) > last_comma:
+                last_comma = idx
+                last_fullstop += 2
+                word += ','
+            # add end of sentences
+            if idx - randrange(10, 20) > last_fullstop:
+                last_comma = last_fullstop = idx
+                word += '.'
+                next_capitalized = True
+            p.append(word)
+
+        # ensure that the paragraph ends with a dot.
+        p = u' '.join(p)
+        if p.endswith(','):
+            p = p[:-1] + '.'
+        elif not p.endswith('.'):
+            p += '.'
+        result.append(p)
+
+    if not html:
+        return u'\n\n'.join(result)
+    return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
+
+
+class LRUCache(object):
+    """A simple LRU Cache implementation."""
+
+    # this is fast for small capacities (something below 1000) but doesn't
+    # scale.  But as long as it's only used as storage for templates this
+    # won't do any harm.
+
+    def __init__(self, capacity):
+        self.capacity = capacity
+        self._mapping = {}
+        self._queue = deque()
+        self._postinit()
+
+    def _postinit(self):
+        # alias all queue methods for faster lookup
+        self._popleft = self._queue.popleft
+        self._pop = self._queue.pop
+        if hasattr(self._queue, 'remove'):
+            self._remove = self._queue.remove
+        self._wlock = allocate_lock()
+        self._append = self._queue.append
+
+    def _remove(self, obj):
+        """Python 2.4 compatibility."""
+        for idx, item in enumerate(self._queue):
+            if item == obj:
+                del self._queue[idx]
+                break
+
+    def __getstate__(self):
+        return {
+            'capacity':     self.capacity,
+            '_mapping':     self._mapping,
+            '_queue':       self._queue
+        }
+
+    def __setstate__(self, d):
+        self.__dict__.update(d)
+        self._postinit()
+
+    def __getnewargs__(self):
+        return (self.capacity,)
+
+    def copy(self):
+        """Return an shallow copy of the instance."""
+        rv = self.__class__(self.capacity)
+        rv._mapping.update(self._mapping)
+        rv._queue = deque(self._queue)
+        return rv
+
+    def get(self, key, default=None):
+        """Return an item from the cache dict or `default`"""
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def setdefault(self, key, default=None):
+        """Set `default` if the key is not in the cache otherwise
+        leave unchanged. Return the value of this key.
+        """
+        try:
+            return self[key]
+        except KeyError:
+            self[key] = default
+            return default
+
+    def clear(self):
+        """Clear the cache."""
+        self._wlock.acquire()
+        try:
+            self._mapping.clear()
+            self._queue.clear()
+        finally:
+            self._wlock.release()
+
+    def __contains__(self, key):
+        """Check if a key exists in this cache."""
+        return key in self._mapping
+
+    def __len__(self):
+        """Return the current size of the cache."""
+        return len(self._mapping)
+
+    def __repr__(self):
+        return '<%s %r>' % (
+            self.__class__.__name__,
+            self._mapping
+        )
+
+    def __getitem__(self, key):
+        """Get an item from the cache. Moves the item up so that it has the
+        highest priority then.
+
+        Raise an `KeyError` if it does not exist.
+        """
+        rv = self._mapping[key]
+        if self._queue[-1] != key:
+            try:
+                self._remove(key)
+            except ValueError:
+                # if something removed the key from the container
+                # when we read, ignore the ValueError that we would
+                # get otherwise.
+                pass
+            self._append(key)
+        return rv
+
+    def __setitem__(self, key, value):
+        """Sets the value for an item. Moves the item up so that it
+        has the highest priority then.
+        """
+        self._wlock.acquire()
+        try:
+            if key in self._mapping:
+                try:
+                    self._remove(key)
+                except ValueError:
+                    # __getitem__ is not locked, it might happen
+                    pass
+            elif len(self._mapping) == self.capacity:
+                del self._mapping[self._popleft()]
+            self._append(key)
+            self._mapping[key] = value
+        finally:
+            self._wlock.release()
+
+    def __delitem__(self, key):
+        """Remove an item from the cache dict.
+        Raise an `KeyError` if it does not exist.
+        """
+        self._wlock.acquire()
+        try:
+            del self._mapping[key]
+            try:
+                self._remove(key)
+            except ValueError:
+                # __getitem__ is not locked, it might happen
+                pass
+        finally:
+            self._wlock.release()
+
+    def items(self):
+        """Return a list of items."""
+        result = [(key, self._mapping[key]) for key in list(self._queue)]
+        result.reverse()
+        return result
+
+    def iteritems(self):
+        """Iterate over all items."""
+        return iter(self.items())
+
+    def values(self):
+        """Return a list of all values."""
+        return [x[1] for x in self.items()]
+
+    def itervalue(self):
+        """Iterate over all values."""
+        return iter(self.values())
+
+    def keys(self):
+        """Return a list of all keys ordered by most recent usage."""
+        return list(self)
+
+    def iterkeys(self):
+        """Iterate over all keys in the cache dict, ordered by
+        the most recent usage.
+        """
+        return reversed(tuple(self._queue))
+
+    __iter__ = iterkeys
+
+    def __reversed__(self):
+        """Iterate over the values in the cache dict, oldest items
+        coming first.
+        """
+        return iter(tuple(self._queue))
+
+    __copy__ = copy
+
+
+# register the LRU cache as mutable mapping if possible
+try:
+    from collections import MutableMapping
+    MutableMapping.register(LRUCache)
+except ImportError:
+    pass
+
+
+class Cycler(object):
+    """A cycle helper for templates."""
+
+    def __init__(self, *items):
+        if not items:
+            raise RuntimeError('at least one item has to be provided')
+        self.items = items
+        self.reset()
+
+    def reset(self):
+        """Resets the cycle."""
+        self.pos = 0
+
+    @property
+    def current(self):
+        """Returns the current item."""
+        return self.items[self.pos]
+
+    def next(self):
+        """Goes one item ahead and returns it."""
+        rv = self.current
+        self.pos = (self.pos + 1) % len(self.items)
+        return rv
+
+
+class Joiner(object):
+    """A joining helper for templates."""
+
+    def __init__(self, sep=u', '):
+        self.sep = sep
+        self.used = False
+
+    def __call__(self):
+        if not self.used:
+            self.used = True
+            return u''
+        return self.sep
+
+
+# try markupsafe first, if that fails go with Jinja2's bundled version
+# of markupsafe.  Markupsafe was previously Jinja2's implementation of
+# the Markup object but was moved into a separate package in a patchleve
+# release
+try:
+    from markupsafe import Markup, escape, soft_unicode
+except ImportError:
+    from ambari_jinja2._markupsafe import Markup, escape, soft_unicode
+
+
+# partials
+try:
+    from functools import partial
+except ImportError:
+    class partial(object):
+        def __init__(self, _func, *args, **kwargs):
+            self._func = _func
+            self._args = args
+            self._kwargs = kwargs
+        def __call__(self, *args, **kwargs):
+            kwargs.update(self._kwargs)
+            return self._func(*(self._args + args), **kwargs)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py
new file mode 100644
index 0000000..0561adf
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/visitor.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.visitor
+    ~~~~~~~~~~~~~~
+
+    This module implements a visitor for the nodes.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from ambari_jinja2.nodes import Node
+
+
+class NodeVisitor(object):
+    """Walks the abstract syntax tree and call visitor functions for every
+    node found.  The visitor functions may return values which will be
+    forwarded by the `visit` method.
+
+    Per default the visitor functions for the nodes are ``'visit_'`` +
+    class name of the node.  So a `TryFinally` node visit function would
+    be `visit_TryFinally`.  This behavior can be changed by overriding
+    the `get_visitor` function.  If no visitor function exists for a node
+    (return value `None`) the `generic_visit` visitor is used instead.
+    """
+
+    def get_visitor(self, node):
+        """Return the visitor function for this node or `None` if no visitor
+        exists for this node.  In that case the generic visit function is
+        used instead.
+        """
+        method = 'visit_' + node.__class__.__name__
+        return getattr(self, method, None)
+
+    def visit(self, node, *args, **kwargs):
+        """Visit a node."""
+        f = self.get_visitor(node)
+        if f is not None:
+            return f(node, *args, **kwargs)
+        return self.generic_visit(node, *args, **kwargs)
+
+    def generic_visit(self, node, *args, **kwargs):
+        """Called if no explicit visitor function exists for a node."""
+        for node in node.iter_child_nodes():
+            self.visit(node, *args, **kwargs)
+
+
+class NodeTransformer(NodeVisitor):
+    """Walks the abstract syntax tree and allows modifications of nodes.
+
+    The `NodeTransformer` will walk the AST and use the return value of the
+    visitor functions to replace or remove the old node.  If the return
+    value of the visitor function is `None` the node will be removed
+    from the previous location otherwise it's replaced with the return
+    value.  The return value may be the original node in which case no
+    replacement takes place.
+    """
+
+    def generic_visit(self, node, *args, **kwargs):
+        for field, old_value in node.iter_fields():
+            if isinstance(old_value, list):
+                new_values = []
+                for value in old_value:
+                    if isinstance(value, Node):
+                        value = self.visit(value, *args, **kwargs)
+                        if value is None:
+                            continue
+                        elif not isinstance(value, Node):
+                            new_values.extend(value)
+                            continue
+                    new_values.append(value)
+                old_value[:] = new_values
+            elif isinstance(old_value, Node):
+                new_node = self.visit(old_value, *args, **kwargs)
+                if new_node is None:
+                    delattr(node, field)
+                else:
+                    setattr(node, field, new_node)
+        return node
+
+    def visit_list(self, node, *args, **kwargs):
+        """As transformers may return lists in some places this method
+        can be used to enforce a list as return value.
+        """
+        rv = self.visit(node, *args, **kwargs)
+        if not isinstance(rv, list):
+            rv = [rv]
+        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg b/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg
new file mode 100644
index 0000000..cc11c5c
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/artwork/jinjalogo.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="300"
+   height="120"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   version="1.0"
+   sodipodi:docbase="/Users/mitsuhiko/Development/ambari_jinja2/artwork"
+   sodipodi:docname="jinjalogo.svg"
+   inkscape:export-filename="/Users/mitsuhiko/Development/ambari_jinja2/docs/_static/jinjabanner.png"
+   inkscape:export-xdpi="60"
+   inkscape:export-ydpi="60"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient6558">
+      <stop
+         style="stop-color:#575757;stop-opacity:1;"
+         offset="0"
+         id="stop6560" />
+      <stop
+         style="stop-color:#2f2f2f;stop-opacity:1;"
+         offset="1"
+         id="stop6562" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="radialGradient6564"
+       cx="61.297766"
+       cy="60.910986"
+       fx="61.297766"
+       fy="60.910986"
+       r="44.688254"
+       gradientTransform="matrix(1,0,0,0.945104,0,3.343747)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="radialGradient6580"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.945104,0.355158,3.334402)"
+       cx="61.297766"
+       cy="60.910986"
+       fx="61.297766"
+       fy="60.910986"
+       r="44.688254" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="linearGradient4173"
+       x1="255.15521"
+       y1="32.347946"
+       x2="279.8912"
+       y2="32.347946"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.8073249,0,0,0.8073249,57.960878,7.4036303)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6558"
+       id="linearGradient5145"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.7902775,0,0,0.82474,60.019977,8.0684132)"
+       x1="255.15521"
+       y1="32.347946"
+       x2="279.8912"
+       y2="32.347946" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8"
+     inkscape:cx="137.4752"
+     inkscape:cy="57.574575"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="300px"
+     height="120px"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1396"
+     inkscape:window-height="900"
+     inkscape:window-x="0"
+     inkscape:window-y="22" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#f4f4f4;fill-opacity:1;stroke:#e7e7e7;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;font-family:Bitstream Vera Sans;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 165.36463,80.874808 L 165.36463,80.874808 L 153.32556,80.874808 L 153.32556,81.8344 L 147.64994,81.8344 L 147.64994,36.035583 L 165.36463,36.035583 L 165.36463,20.333129 C 170.58154,21.031083 173.07533,22.077914 172.84609,23.473621 C 172.78871,24.055258 172.21545,24.549594 171.12624,24.956624 L 171.12624,36.035583 L 189.09895,36.035583 L 189.09895,82.532286 L 183.33733,82.532286 L 183.33733,80.874808 L 171.12624,80.874808 L 171.12624,102.94548 L 165.36463,102.94548 L 165.36463,80.874808 M 153.32556,55.489173 L 153.32556,55.489173 L 165.36463,55.489173 L 165.36463,41.793146 L 153.32556,41.793146 L 153.32556,55.489173 M 171.12624,55.489173 L 171.12624,55.489173 L 183.33733,55.489173 L 183.33733,41.793146 L 171.12624,41.793146 L 171.12624,55.489173 M 183.33733,61.333977 L 183.33733,61.333977 L 171.12624,61.333977 L 171.12624,75.030006 L 183.33733,75.030006 L 183.33733,61.333977 M 165.36463,61.333977 L 165.36463,61.333977 L 153.32556,61.333977 L 153.32556,75.030006 L 165.364
 63,75.030006 L 165.36463,61.333977 M 132.85897,59.414792 C 137.33069,63.136883 140.99969,67.934848 143.86618,73.808701 L 139.13654,77.385372 C 137.24467,72.965445 134.6362,69.12707 131.31114,65.87024 L 131.31114,102.94548 L 125.63554,102.94548 L 125.63554,68.57455 C 122.31042,71.947693 118.52671,74.913707 114.28436,77.47261 L 109.64069,73.372526 C 121.50782,67.091566 130.62312,55.489212 136.98668,38.565417 L 116.26221,38.565417 L 116.26221,32.720615 L 125.80754,32.720615 L 125.80754,20.333129 C 130.85245,21.031083 133.31761,22.048838 133.20299,23.386383 C 133.14561,24.026183 132.57235,24.549594 131.48307,24.956624 L 131.48307,32.720615 L 140.77043,32.720615 L 143.60824,36.733469 C 140.68444,45.51526 137.10137,53.075692 132.85897,59.414792 M 254.11016,49.469901 L 254.11016,49.469901 L 254.11016,20.333129 C 259.21243,21.031083 261.67755,22.048838 261.50562,23.386383 C 261.44823,23.909869 261.04699,24.346044 260.30172,24.694917 C 260.30164,24.694986 260.30164,24.694986 260.30172,24.694
 917 L 260.30172,24.694917 L 259.78578,24.956624 L 259.78578,49.469901 L 277.15652,49.469901 L 277.15652,55.227471 L 259.78578,55.227471 L 259.78578,93.785712 L 281.45616,93.785712 L 281.45616,99.63051 L 232.35378,99.63051 L 232.35378,93.785712 L 254.11016,93.785712 L 254.11016,55.227471 L 236.22346,55.227471 L 236.22346,49.469901 L 254.11016,49.469901 M 225.5603,59.327554 C 231.12111,63.107798 235.62145,67.876693 239.06127,73.634235 L 234.76157,77.647079 C 231.60845,72.180322 227.82475,67.934848 223.41044,64.910648 L 223.41044,102.94548 L 217.73484,102.94548 L 217.73484,67.44049 C 212.91919,71.627831 207.70222,75.030021 202.084,77.647079 L 197.87027,73.198053 C 212.66118,66.917101 224.01239,55.372897 231.92377,38.565417 L 205.35172,38.565417 L 205.35172,32.720615 L 217.99283,32.720615 L 217.99283,20.333129 C 223.03774,21.031083 225.50291,22.048838 225.38829,23.386383 C 225.33089,24.026183 224.75765,24.549594 223.66837,24.956624 L 223.66837,32.720615 L 236.22346,32.720615 L 238.80326
 ,36.733469 C 235.13421,45.51526 230.71987,53.046611 225.5603,59.327554"
+       id="text4761" />
+    <path
+       style="font-size:44.09793472px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#b41717;fill-opacity:1;stroke:#7f2828;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Candara;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 149.14708,37.774469 C 148.97807,41.117899 148.84526,44.824225 148.74871,48.893456 C 148.67626,52.962754 148.3818,70.641328 148.38184,75.524422 C 148.3818,79.065795 148.05588,81.991266 147.40406,84.300835 C 146.75219,86.610422 145.72612,88.557071 144.32585,90.140779 C 142.94969,91.724494 141.17522,92.901283 139.00239,93.671139 C 136.82953,94.440996 134.22211,94.825935 131.18014,94.825935 C 128.83828,94.825935 126.73787,94.59498 124.87889,94.133049 L 125.4221,89.31593 C 127.13623,90.0418 128.92278,90.404734 130.78177,90.404733 C 132.85805,90.404734 134.66875,90.140782 136.2139,89.612876 C 137.78315,89.062981 139.02651,88.216133 139.94396,87.072335 C 140.8855,85.928548 141.54942,84.520804 141.93572,82.8491 C 142.34613,81.177412 142.55134,78.988811 142.55136,76.283285 C 142.55134,66.297119 142.62852,44.659257 142.26641,37.774469 L 149.14708,37.774469 M 166.38498,80.732697 L 159.83024,80.732697 C 160.16821,76.333498 160.33723,71.307412 160.33723,65.654424 C 160.33723,59.2976 
 159.91471,53.963567 159.06973,49.652319 L 166.31257,48.761483 C 166.02284,53.358679 165.87799,58.98965 165.87799,65.654424 C 165.87799,70.933479 166.04699,75.959565 166.38498,80.732697 M 167.90601,39.490159 C 167.90598,40.611994 167.5076,41.590815 166.7109,42.42662 C 165.91418,43.240515 164.79155,43.647442 163.343,43.647399 C 162.11172,43.647442 161.146,43.295504 160.44588,42.591595 C 159.76988,41.865769 159.43188,40.996927 159.43188,39.98507 C 159.43188,38.885304 159.84231,37.928485 160.66315,37.114591 C 161.48399,36.30078 162.61869,35.893853 164.06727,35.893811 C 165.25023,35.893853 166.17975,36.256783 166.85575,36.982609 C 167.55588,37.686526 167.90598,38.522373 167.90601,39.490159 M 206.72748,80.732697 L 200.13651,80.732697 C 200.66763,74.947749 200.93319,68.634899 200.9332,61.794122 C 200.93319,58.406756 200.1727,56.097177 198.65174,54.865371 C 197.15487,53.61163 195.00619,52.984747 192.20564,52.984714 C 188.77731,52.984747 185.61465,54.117535 182.71753,56.383099 C 182.71753,63
 .883761 182.76583,72.000287 182.86238,80.732697 L 176.27142,80.732697 C 176.68182,73.254058 176.88707,67.843042 176.88707,64.499632 C 176.88707,59.352589 176.3559,54.359493 175.29363,49.520339 L 181.66734,48.695493 L 182.35539,52.720761 L 182.64511,52.720761 C 186.21823,49.773323 190.04483,48.299592 194.12499,48.299567 C 198.13265,48.299592 201.23499,49.113454 203.43201,50.741118 C 205.62895,52.346863 206.72747,55.217334 206.72748,59.352563 C 206.72747,59.770507 206.70331,60.595362 206.65507,61.827118 C 206.60675,63.058915 206.5826,63.883761 206.58262,64.30167 C 206.5826,67.975018 206.63088,73.452022 206.72748,80.732697 M 222.69791,48.695493 C 222.28747,55.514282 222.08225,62.355041 222.08225,69.21778 C 222.08225,71.043461 222.14262,73.463019 222.26332,76.476468 C 222.40822,79.467925 222.4806,81.502559 222.48063,82.580363 C 222.4806,89.685068 219.51105,93.996287 213.57195,95.514024 L 211.76124,93.006484 C 213.90995,91.356766 215.2378,89.597085 215.74478,87.727431 C 216.49321,85.0439
 12 216.86743,79.324953 216.86743,70.570535 C 216.86743,61.178248 216.3846,54.16153 215.41887,49.520339 L 222.69791,48.695493 M 224.2551,39.490159 C 224.2551,40.611994 223.85673,41.590815 223.06006,42.42662 C 222.26332,43.240515 221.14069,43.647442 219.69213,43.647399 C 218.46084,43.647442 217.49515,43.295504 216.795,42.591595 C 216.119,41.865769 215.781,40.996927 215.781,39.98507 C 215.781,38.885304 216.19144,37.928485 217.01231,37.114591 C 217.83316,36.30078 218.96785,35.893853 220.4164,35.893811 C 221.5994,35.893853 222.52889,36.256783 223.20492,36.982609 C 223.90503,37.686526 224.2551,38.522373 224.2551,39.490159 M 259.60008,80.732697 L 253.91446,80.930661 C 253.62473,79.852857 253.47987,78.830045 253.4799,77.862216 L 253.11774,77.862216 C 250.14817,80.325772 246.10427,81.557546 240.98606,81.557547 C 238.20962,81.557546 235.8195,80.820682 233.81563,79.346948 C 231.81178,77.851221 230.80988,75.728607 230.80988,72.979099 C 230.80988,69.591724 232.37914,66.875216 235.51769,64.829574
  C 238.65625,62.761967 244.48667,61.67316 253.00913,61.563165 C 253.08155,61.035275 253.11772,60.430386 253.11774,59.748497 C 253.11772,57.043003 252.32104,55.239336 250.72765,54.337474 C 249.15832,53.435661 246.76819,52.984747 243.55721,52.984714 C 239.76681,52.984747 236.03678,53.413668 232.3671,54.271484 L 232.9827,49.718301 C 236.60411,48.77251 240.76873,48.299592 245.47658,48.299567 C 249.77395,48.299592 253.09359,49.113454 255.43545,50.741118 C 257.77728,52.346863 258.94819,55.096363 258.94824,58.989625 C 258.94819,60.023469 258.88785,61.904117 258.76715,64.631608 C 258.67054,67.337133 258.62228,69.140806 258.6223,70.042632 C 258.62228,74.045913 258.94819,77.609265 259.60008,80.732697 M 253.19019,74.331856 C 253.06945,70.988469 253.00909,67.986016 253.00913,65.324484 C 248.47027,65.324498 245.01786,65.632443 242.65187,66.248318 C 238.69248,67.348131 236.71278,69.448748 236.71278,72.550177 C 236.71278,75.541643 239.03044,77.037371 243.66588,77.037366 C 247.64942,77.037371 250.8
 2416,76.135534 253.19019,74.331856"
+       id="text3736"
+       sodipodi:nodetypes="ccsscssccscccsccccsccsccsscsssccccscscccsccccscsssccscscccscccsscsssccccccscsccscsccscscsccccssc" />
+    <path
+       style="fill:url(#radialGradient6564);fill-opacity:1.0;fill-rule:evenodd;stroke:#323232;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 105.45673,18.675923 C 105.45673,18.675923 88.211949,26.918461 74.172834,28.737898 C 60.133727,30.557333 33.360434,32.377571 28.045622,31.093256 C 22.730818,29.808941 18.915645,28.309196 18.915645,28.309196 L 20.021441,32.056583 L 16.609513,35.052471 L 17.2144,36.121726 L 18.61792,36.22764 L 22.92773,36.762252 L 23.532621,38.688909 L 25.937975,38.905784 L 27.143021,42.970927 C 27.143021,42.970927 32.254764,43.399628 33.758953,43.399628 C 35.263142,43.399628 38.271966,43.187802 38.271966,43.187802 L 38.371202,44.791657 L 39.477002,45.003495 L 39.477002,46.824227 L 37.066917,48.967759 L 37.671807,49.073671 L 37.671807,49.820127 C 37.671807,49.820127 32.255457,50.252157 30.049301,49.93109 C 27.843157,49.610006 27.440747,49.608286 27.440747,49.608286 L 27.242258,49.820127 L 27.143021,50.783455 L 27.643946,50.783455 L 27.84242,54.959544 L 38.976091,54.530844 L 38.172728,68.980747 L 38.073481,70.796442 L 28.645781,70.261816 L 28.546544,66.408513 L 30.649462,66.408513 L 30.85267
 3,64.910557 L 32.757107,64.481857 L 33.059555,64.058192 L 25.937975,62.343374 L 20.522364,63.947229 L 21.42496,64.698732 L 22.327572,64.698732 L 22.426809,65.984848 L 24.331254,66.09076 L 24.331254,69.838147 L 22.228335,70.372777 L 22.630009,71.225146 L 23.130934,71.547931 L 23.130934,74.437917 L 24.435218,74.437917 L 24.435218,87.813529 L 22.327572,88.13632 L 22.630009,91.989617 L 23.929569,92.206492 L 23.731093,100.98236 L 29.449141,101.08826 L 28.244105,92.418334 L 36.868446,92.206492 L 36.268285,96.912181 L 35.464925,100.23086 L 44.188501,100.33677 L 44.287739,91.777793 L 50.303506,91.243181 L 50.005786,96.700351 L 49.802585,99.90807 L 54.920484,99.90807 L 54.717274,91.132217 L 55.421397,91.243181 L 55.619882,87.067076 L 54.816521,87.067076 L 54.518798,85.352258 L 54.017874,80.429702 L 54.216359,74.760706 L 55.31743,74.760706 L 55.31743,71.336105 L 53.913913,71.442015 L 54.117112,67.402096 L 55.747469,67.240708 L 55.823083,65.929374 L 56.749319,65.793192 L 57.699176,65.071956 L 
 51.985842,63.896802 L 46.31977,65.15265 L 46.872668,66.060507 L 47.47283,66.010066 L 48.172228,65.984848 L 48.299828,67.639144 L 49.878196,67.563497 L 49.906548,71.144447 L 43.111042,70.988097 L 43.337879,67.160002 L 43.559978,63.679927 L 43.559978,59.105378 L 43.763188,54.288748 L 57.373101,53.592733 L 73.567955,52.659674 L 73.71917,55.736265 L 73.142647,63.120082 L 72.892183,69.9945 L 66.928387,69.888585 L 66.900039,65.071956 L 69.106918,64.991267 L 69.206169,63.629486 L 70.108765,63.493308 L 70.061506,63.226006 L 70.964116,63.175568 L 71.465028,62.504773 L 64.721507,60.926122 L 58.001612,62.368592 L 58.4789,63.200785 L 59.230285,63.1453 L 59.230285,63.523577 L 60.156518,63.523577 L 60.156518,65.046738 L 62.136575,65.071956 L 62.112937,69.298485 L 60.109259,69.298485 L 60.080907,70.261816 L 60.785031,70.342507 L 60.70942,74.009202 L 62.188552,74.089909 L 62.013701,88.620507 L 60.057282,89.018952 L 60.080907,89.714967 L 60.761406,89.714967 L 60.761406,93.437137 L 61.886113,93.43713
 7 L 61.588391,98.52109 L 61.210343,102.95945 L 68.331912,103.14605 L 68.105084,99.29275 L 67.580538,96.085028 L 67.476575,93.300955 L 73.520696,93.195041 L 73.345845,97.502272 L 73.317494,102.05159 L 76.729426,102.3189 L 81.3653,102.1323 L 82.820807,101.70358 L 82.017437,99.26753 L 81.818959,95.439438 L 81.440912,92.710853 L 87.206218,92.499027 L 86.955759,95.842931 L 86.932133,101.08826 L 89.238253,101.30009 L 91.520751,101.24965 L 92.621828,100.90165 L 91.969693,95.923633 L 91.747577,92.176239 L 92.725793,92.070324 L 92.749427,88.726422 L 93.02352,88.670945 L 92.976244,87.949712 L 91.846823,87.949712 L 91.619996,85.488427 L 91.520751,74.811143 L 92.371377,74.785924 L 92.371377,71.280616 L 92.725793,71.336105 L 92.725793,70.640088 L 91.468773,70.529127 L 91.497126,66.463987 L 93.600043,66.277382 L 93.477182,64.910557 L 94.403419,64.829863 L 94.351424,64.562549 L 95.580099,63.947229 L 89.337489,62.69138 L 82.995657,63.977495 L 83.39733,64.723951 L 84.375543,64.643256 L 84.427528,64.
 966046 L 85.254515,64.966046 L 85.301775,66.569901 L 87.357445,66.544681 L 87.532293,70.478688 L 80.264217,70.423216 L 79.413593,64.512124 L 78.733106,61.380041 L 78.184923,55.761484 L 78.510996,52.473053 L 92.999878,51.373557 L 93.047136,46.476221 L 93.774891,46.289613 L 93.727651,45.543159 L 93.174743,45.220372 C 93.174629,45.220372 85.252181,46.395266 82.745197,46.66284 C 82.0389,46.738209 82.09239,46.733258 81.516524,46.79397 L 81.440912,45.886118 L 78.444837,44.317564 L 78.482644,42.491786 L 79.512842,42.461518 L 79.588444,39.949808 C 79.588444,39.949808 85.728225,39.546834 88.009582,39.0117 C 90.290937,38.476559 93.524432,37.942456 93.524432,37.942456 L 95.055545,33.79662 L 98.089437,32.913987 L 98.339888,32.217972 L 105.20628,30.316548 L 105.98602,29.676006 L 103.37744,23.976741 L 103.62792,22.690624 L 104.95584,21.994611 L 105.91041,19.079404 L 105.45673,18.675923 z M 72.466874,40.403728 L 72.429067,42.476654 L 73.983813,42.542211 L 73.884576,44.509221 L 70.836515,46.506487 
 L 70.647496,47.081457 L 71.876167,47.091543 L 71.866712,47.575729 L 62.552432,48.029652 L 62.613863,46.652742 L 63.039175,45.966809 L 63.067524,45.528025 L 63.07698,44.579832 L 63.341609,43.949374 L 63.440849,43.439982 L 63.440849,43.076841 L 63.842533,41.47297 L 72.466874,40.403728 z M 52.987688,42.168984 L 52.760853,43.561027 L 53.488599,44.418431 L 53.441349,45.916386 L 54.117112,46.960408 L 53.942262,48.191039 L 54.443185,48.912273 L 44.939872,49.2855 L 44.916247,48.967759 L 46.017333,48.831579 L 46.069307,48.428097 L 43.66394,47.121797 L 43.536351,45.03375 L 44.689411,44.978276 L 44.788661,42.72883 L 52.987688,42.168984 z M 67.051262,74.276518 L 72.81657,74.649742 L 72.618099,82.411833 L 73.36947,88.776857 L 67.254465,88.565018 L 67.051262,74.276518 z M 28.44258,74.599304 L 37.671807,75.078442 L 36.868446,80.429702 L 36.868446,84.928593 L 37.520583,87.440302 L 28.494569,87.869006 L 28.44258,74.599304 z M 87.508658,74.649742 L 87.508658,87.924488 L 81.644113,88.353194 L 81.44091
 2,81.342592 L 80.788764,74.811143 L 87.508658,74.649742 z M 43.087416,74.947312 L 49.906548,74.972531 L 49.977434,87.278902 L 43.611966,87.389863 L 43.285891,83.400379 L 43.262266,79.441156 L 43.087416,74.947312 z "
+       id="path4735" />
+  </g>
+</svg>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py
new file mode 100644
index 0000000..96a81c1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_alt_unicode.py
@@ -0,0 +1,13 @@
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import Name, BlankLine
+
+
+class FixAltUnicode(fixer_base.BaseFix):
+    PATTERN = """
+    func=funcdef< 'def' name='__unicode__'
+                  parameters< '(' NAME ')' > any+ >
+    """
+
+    def transform(self, node, results):
+        name = results['name']
+        name.replace(Name('__str__', prefix=name.prefix))


[42/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst b/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst
new file mode 100644
index 0000000..912bd39
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/intro.rst
@@ -0,0 +1,168 @@
+Introduction
+============
+
+This is the documentation for the Jinja2 general purpose templating language.
+Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
+fast and secure.
+
+If you have any exposure to other text-based template languages, such as Smarty or
+Django, you should feel right at home with Jinja2.  It's both designer and
+developer friendly by sticking to Python's principles and adding functionality
+useful for templating environments.
+
+The key-features are...
+
+-   ... **configurable syntax**.  If you are generating LaTeX or other formats
+    with Jinja2 you can change the delimiters to something that integrates better
+    into the LaTeX markup.
+
+-   ... **fast**.  While performance is not the primarily target of Jinja2 it's
+    surprisingly fast.  The overhead compared to regular Python code was reduced
+    to the very minimum.
+
+-   ... **easy to debug**.  Jinja2 integrates directly into the python traceback
+    system which allows you to debug Jinja2 templates with regular python
+    debugging helpers.
+
+-   ... **secure**.  It's possible to evaluate untrusted template code if the
+    optional sandbox is enabled.  This allows Jinja2 to be used as templating
+    language for applications where users may modify the template design.
+
+
+Prerequisites
+-------------
+
+Jinja2 needs at least **Python 2.4** to run.  Additionally a working C-compiler
+that can create python extensions should be installed for the debugger if you
+are using Python 2.4.
+
+If you don't have a working C-compiler and you are trying to install the source
+release with the debugsupport you will get a compiler error.
+
+.. _ctypes: http://python.net/crew/theller/ctypes/
+
+
+Installation
+------------
+
+You have multiple ways to install Jinja2.  If you are unsure what to do, go
+with the Python egg or tarball.
+
+As a Python egg (via easy_install)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can install the most recent Jinja2 version using `easy_install`_ or `pip`_::
+
+    easy_install Jinja2
+    pip install Jinja2
+
+This will install a Jinja2 egg in your Python installation's site-packages
+directory.
+
+(If you are installing from the windows command line omit the `sudo` and make
+sure to run the command as user with administrator rights)
+
+From the tarball release
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1.  Download the most recent tarball from the `download page`_
+2.  Unpack the tarball
+3.  ``sudo python setup.py install``
+
+Note that you either have to have setuptools or `distribute`_ installed,
+the latter is preferred.
+
+This will install Jinja2 into your Python installation's site-packages directory.
+
+.. _distribute: http://pypi.python.org/pypi/distribute
+
+Installing the development version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1.  Install `git`_
+2.  ``git clone git://github.com/mitsuhiko/ambari_jinja2.git``
+3.  ``cd ambari_jinja2``
+4.  ``ln -s ambari_jinja2 /usr/lib/python2.X/site-packages``
+
+As an alternative to steps 4 you can also do ``python setup.py develop``
+which will install the package via distribute in development mode.  This also
+has the advantage that the C extensions are compiled.
+
+.. _download page: http://pypi.python.org/pypi/Jinja2
+.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
+.. _pip: http://pypi.python.org/pypi/pip
+.. _git: http://git-scm.org/
+
+
+More Speed with MarkupSafe
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As of version 2.5.1 Jinja2 will check for an installed `MarkupSafe`_
+module.  If it can find it, it will use the Markup class of that module
+instead of the one that comes with Jinja2.  `MarkupSafe` replaces the
+older speedups module that came with Jinja2 and has the advantage that is
+has a better setup script and will automatically attempt to install the C
+version and nicely fall back to a pure Python implementation if that is
+not possible.
+
+The C implementation of MarkupSafe is much faster and recommended when
+using Jinja2 with autoescaping.
+
+.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
+
+
+Enable the debug support Module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default Jinja2 will not compile the debug support module.  Enabling this
+will fail if you don't have the Python headers or a working compiler.  This
+is often the case if you are installing Jinja2 from a windows machine.
+
+Because the debug support is only necessary for Python 2.4 you will not
+have to do this unless you run 2.4::
+
+    sudo python setup.py --with-debugsupport install
+
+
+Basic API Usage
+---------------
+
+This section gives you a brief introduction to the Python API for Jinja2
+templates.
+
+The most basic way to create a template and render it is through
+:class:`~ambari_jinja2.Template`.  This however is not the recommended way to
+work with it if your templates are not loaded from strings but the file
+system or another data source:
+
+>>> from ambari_jinja2 import Template
+>>> template = Template('Hello {{ name }}!')
+>>> template.render(name='John Doe')
+u'Hello John Doe!'
+
+By creating an instance of :class:`~ambari_jinja2.Template` you get back a new template
+object that provides a method called :meth:`~ambari_jinja2.Template.render` which when
+called with a dict or keyword arguments expands the template.  The dict
+or keywords arguments passed to the template are the so-called "context"
+of the template.
+
+What you can see here is that Jinja2 is using unicode internally and the
+return value is an unicode string.  So make sure that your application is
+indeed using unicode internally.
+
+
+Experimental Python 3 Support
+-----------------------------
+
+Jinja 2.3 brings experimental support for Python 3.  It means that all
+unittests pass on the new version, but there might still be small bugs in
+there and behavior might be inconsistent.  If you notice any bugs, please
+provide feedback in the `Jinja bug tracker`_.
+
+Also please keep in mind that the documentation is written with Python 2
+in mind, you will have to adapt the shown code examples to Python 3 syntax
+for yourself.
+
+
+.. _Jinja bug tracker: http://github.com/mitsuhiko/ambari_jinja2/issues

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py b/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py
new file mode 100644
index 0000000..da95354
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/jinjaext.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+"""
+    Jinja Documentation Extensions
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Support for automatically documenting filters and tests.
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: BSD.
+"""
+import os
+import re
+import inspect
+import ambari_jinja2
+from itertools import islice
+from types import BuiltinFunctionType
+from docutils import nodes
+from docutils.statemachine import ViewList
+from sphinx.ext.autodoc import prepare_docstring
+from sphinx.application import TemplateBridge
+from pygments.style import Style
+from pygments.token import Keyword, Name, Comment, String, Error, \
+     Number, Operator, Generic
+from ambari_jinja2 import Environment, FileSystemLoader
+
+
+def parse_rst(state, content_offset, doc):
+    node = nodes.section()
+    # hack around title style bookkeeping
+    surrounding_title_styles = state.memo.title_styles
+    surrounding_section_level = state.memo.section_level
+    state.memo.title_styles = []
+    state.memo.section_level = 0
+    state.nested_parse(doc, content_offset, node, match_titles=1)
+    state.memo.title_styles = surrounding_title_styles
+    state.memo.section_level = surrounding_section_level
+    return node.children
+
+
+class JinjaStyle(Style):
+    title = 'Jinja Style'
+    default_style = ""
+    styles = {
+        Comment:                    'italic #aaaaaa',
+        Comment.Preproc:            'noitalic #B11414',
+        Comment.Special:            'italic #505050',
+
+        Keyword:                    'bold #B80000',
+        Keyword.Type:               '#808080',
+
+        Operator.Word:              'bold #B80000',
+
+        Name.Builtin:               '#333333',
+        Name.Function:              '#333333',
+        Name.Class:                 'bold #333333',
+        Name.Namespace:             'bold #333333',
+        Name.Entity:                'bold #363636',
+        Name.Attribute:             '#686868',
+        Name.Tag:                   'bold #686868',
+        Name.Decorator:             '#686868',
+
+        String:                     '#AA891C',
+        Number:                     '#444444',
+
+        Generic.Heading:            'bold #000080',
+        Generic.Subheading:         'bold #800080',
+        Generic.Deleted:            '#aa0000',
+        Generic.Inserted:           '#00aa00',
+        Generic.Error:              '#aa0000',
+        Generic.Emph:               'italic',
+        Generic.Strong:             'bold',
+        Generic.Prompt:             '#555555',
+        Generic.Output:             '#888888',
+        Generic.Traceback:          '#aa0000',
+
+        Error:                      '#F00 bg:#FAA'
+    }
+
+
+_sig_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))')
+
+
+def format_function(name, aliases, func):
+    lines = inspect.getdoc(func).splitlines()
+    signature = '()'
+    if isinstance(func, BuiltinFunctionType):
+        match = _sig_re.match(lines[0])
+        if match is not None:
+            del lines[:1 + bool(lines and not lines[0])]
+            signature = match.group(1)
+    else:
+        try:
+            argspec = inspect.getargspec(func)
+            if getattr(func, 'environmentfilter', False) or \
+               getattr(func, 'contextfilter', False):
+                del argspec[0][0]
+            signature = inspect.formatargspec(*argspec)
+        except:
+            pass
+    result = ['.. function:: %s%s' % (name, signature), '']
+    result.extend('    ' + line for line in lines)
+    if aliases:
+        result.extend(('', '    :aliases: %s' % ', '.join(
+                      '``%s``' % x for x in sorted(aliases))))
+    return result
+
+
+def dump_functions(mapping):
+    def directive(dirname, arguments, options, content, lineno,
+                      content_offset, block_text, state, state_machine):
+        reverse_mapping = {}
+        for name, func in mapping.iteritems():
+            reverse_mapping.setdefault(func, []).append(name)
+        filters = []
+        for func, names in reverse_mapping.iteritems():
+            aliases = sorted(names, key=lambda x: len(x))
+            name = aliases.pop()
+            filters.append((name, aliases, func))
+        filters.sort()
+
+        result = ViewList()
+        for name, aliases, func in filters:
+            for item in format_function(name, aliases, func):
+                result.append(item, '<jinjaext>')
+
+        node = nodes.paragraph()
+        state.nested_parse(result, content_offset, node)
+        return node.children
+    return directive
+
+
+from ambari_jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS
+jinja_filters = dump_functions(DEFAULT_FILTERS)
+jinja_tests = dump_functions(DEFAULT_TESTS)
+
+
+def jinja_nodes(dirname, arguments, options, content, lineno,
+                content_offset, block_text, state, state_machine):
+    from ambari_jinja2.nodes import Node
+    doc = ViewList()
+    def walk(node, indent):
+        p = ' ' * indent
+        sig = ', '.join(node.fields)
+        doc.append(p + '.. autoclass:: %s(%s)' % (node.__name__, sig), '')
+        if node.abstract:
+            members = []
+            for key, name in node.__dict__.iteritems():
+                if not key.startswith('_') and \
+                   not hasattr(node.__base__, key) and callable(name):
+                    members.append(key)
+            if members:
+                members.sort()
+                doc.append('%s :members: %s' % (p, ', '.join(members)), '')
+        if node.__base__ != object:
+            doc.append('', '')
+            doc.append('%s :Node type: :class:`%s`' %
+                       (p, node.__base__.__name__), '')
+        doc.append('', '')
+        children = node.__subclasses__()
+        children.sort(key=lambda x: x.__name__.lower())
+        for child in children:
+            walk(child, indent)
+    walk(Node, 0)
+    return parse_rst(state, content_offset, doc)
+
+
+def inject_toc(app, doctree, docname):
+    titleiter = iter(doctree.traverse(nodes.title))
+    try:
+        # skip first title, we are not interested in that one
+        titleiter.next()
+        title = titleiter.next()
+        # and check if there is at least another title
+        titleiter.next()
+    except StopIteration:
+        return
+    tocnode = nodes.section('')
+    tocnode['classes'].append('toc')
+    toctitle = nodes.section('')
+    toctitle['classes'].append('toctitle')
+    toctitle.append(nodes.title(text='Table Of Contents'))
+    tocnode.append(toctitle)
+    tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1]
+    title.parent.insert(title.parent.children.index(title), tocnode)
+
+
+def setup(app):
+    app.add_directive('jinjafilters', jinja_filters, 0, (0, 0, 0))
+    app.add_directive('jinjatests', jinja_tests, 0, (0, 0, 0))
+    app.add_directive('jinjanodes', jinja_nodes, 0, (0, 0, 0))
+    # uncomment for inline toc.  links are broken unfortunately
+    ##app.connect('doctree-resolved', inject_toc)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst b/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst
new file mode 100644
index 0000000..d008408
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/sandbox.rst
@@ -0,0 +1,46 @@
+Sandbox
+=======
+
+The Jinja2 sandbox can be used to evaluate untrusted code.  Access to unsafe
+attributes and methods is prohibited.
+
+Assuming `env` is a :class:`SandboxedEnvironment` in the default configuration
+the following piece of code shows how it works:
+
+>>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
+u''
+>>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
+Traceback (most recent call last):
+  ...
+SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
+
+
+.. module:: ambari_jinja2.sandbox
+
+.. autoclass:: SandboxedEnvironment([options])
+    :members: is_safe_attribute, is_safe_callable
+
+.. autoclass:: ImmutableSandboxedEnvironment([options])
+
+.. autoexception:: SecurityError
+
+.. autofunction:: unsafe
+
+.. autofunction:: is_internal_attribute
+
+.. autofunction:: modifies_known_mutable
+
+.. admonition:: Note
+
+    The Jinja2 sandbox alone is no solution for perfect security.  Especially
+    for web applications you have to keep in mind that users may create
+    templates with arbitrary HTML in so it's crucial to ensure that (if you
+    are running multiple users on the same server) they can't harm each other
+    via JavaScript insertions and much more.
+
+    Also the sandbox is only as good as the configuration.  We stronly
+    recommend only passing non-shared resources to the template and use
+    some sort of whitelisting for attributes.
+
+    Also keep in mind that templates may raise runtime or compile time errors,
+    so make sure to catch them.

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst b/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst
new file mode 100644
index 0000000..ba3cfb1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/switching.rst
@@ -0,0 +1,242 @@
+Switching from other Template Engines
+=====================================
+
+.. highlight:: html+jinja
+
+If you have used a different template engine in the past and want to swtich
+to Jinja2 here is a small guide that shows the basic syntatic and semantic
+changes between some common, similar text template engines for Python.
+
+Jinja1
+------
+
+Jinja2 is mostly compatible with Jinja1 in terms of API usage and template
+syntax.  The differences between Jinja1 and 2 are explained in the following
+list.
+
+API
+~~~
+
+Loaders
+    Jinja2 uses a different loader API.  Because the internal representation
+    of templates changed there is no longer support for external caching
+    systems such as memcached.  The memory consumed by templates is comparable
+    with regular Python modules now and external caching doesn't give any
+    advantage.  If you have used a custom loader in the past have a look at
+    the new :ref:`loader API <loaders>`.
+
+Loading templates from strings
+    In the past it was possible to generate templates from a string with the
+    default environment configuration by using `jinja.from_string`.  Jinja2
+    provides a :class:`Template` class that can be used to do the same, but
+    with optional additional configuration.
+
+Automatic unicode conversion
+    Jinja1 performed automatic conversion of bytestrings in a given encoding
+    into unicode objects.  This conversion is no longer implemented as it
+    was inconsistent as most libraries are using the regular Python ASCII
+    bytestring to Unicode conversion.  An application powered by Jinja2
+    *has to* use unicode internally everywhere or make sure that Jinja2 only
+    gets unicode strings passed.
+
+i18n
+    Jinja1 used custom translators for internationalization.  i18n is now
+    available as Jinja2 extension and uses a simpler, more gettext friendly
+    interface and has support for babel.  For more details see
+    :ref:`i18n-extension`.
+
+Internal methods
+    Jinja1 exposed a few internal methods on the environment object such
+    as `call_function`, `get_attribute` and others.  While they were marked
+    as being an internal method it was possible to override them.  Jinja2
+    doesn't have equivalent methods.
+
+Sandbox
+    Jinja1 was running sandbox mode by default.  Few applications actually
+    used that feature so it became optional in Jinja2.  For more details
+    about the sandboxed execution see :class:`SandboxedEnvironment`.
+
+Context
+    Jinja1 had a stacked context as storage for variables passed to the
+    environment.  In Jinja2 a similar object exists but it doesn't allow
+    modifications nor is it a singleton.  As inheritance is dynamic now
+    multiple context objects may exist during template evaluation.
+
+Filters and Tests
+    Filters and tests are regular functions now.  It's no longer necessary
+    and allowed to use factory functions.
+
+
+Templates
+~~~~~~~~~
+
+Jinja2 has mostly the same syntax as Jinja1.  What's different is that
+macros require parentheses around the argument list now.
+
+Additionally Jinja2 allows dynamic inheritance now and dynamic includes.
+The old helper function `rendertemplate` is gone now, `include` can be used
+instead.  Includes no longer import macros and variable assignments, for
+that the new `import` tag is used.  This concept is explained in the
+:ref:`import` documentation.
+
+Another small change happened in the `for`-tag.  The special loop variable
+doesn't have a `parent` attribute, instead you have to alias the loop
+yourself.  See :ref:`accessing-the-parent-loop` for more details.
+
+
+Django
+------
+
+If you have previously worked with Django templates, you should find
+Jinja2 very familiar.  In fact, most of the syntax elements look and
+work the same.
+
+However, Jinja2 provides some more syntax elements covered in the
+documentation and some work a bit different.
+
+This section covers the template changes.  As the API is fundamentally
+different we won't cover it here.
+
+Method Calls
+~~~~~~~~~~~~
+
+In Django method calls work implicitly.  With Jinja2 you have to specify that
+you want to call an object.  Thus this Django code::
+
+    {% for page in user.get_created_pages %}
+        ...
+    {% endfor %}
+    
+will look like this in Jinja::
+
+    {% for page in user.get_created_pages() %}
+        ...
+    {% endfor %}
+
+This allows you to pass variables to the function which is also used for macros
+which is not possible in Django.
+
+Conditions
+~~~~~~~~~~
+
+In Django you can use the following constructs to check for equality::
+
+    {% ifequal foo "bar" %}
+        ...
+    {% else %}
+        ...
+    {% endifequal %}
+
+In Jinja2 you can use the normal if statement in combination with operators::
+
+    {% if foo == 'bar' %}
+        ...
+    {% else %}
+        ...
+    {% endif %}
+
+You can also have multiple elif branches in your template::
+
+    {% if something %}
+        ...
+    {% elif otherthing %}
+        ...
+    {% elif foothing %}
+        ...
+    {% else %}
+        ...
+    {% endif %}
+
+Filter Arguments
+~~~~~~~~~~~~~~~~
+
+Jinja2 provides more than one argument for filters.  Also the syntax for
+argument passing is different.  A template that looks like this in Django::
+
+    {{ items|join:", " }}
+
+looks like this in Jinja2::
+
+    {{ items|join(', ') }}
+
+In fact it's a bit more verbose but it allows different types of arguments -
+including variables - and more than one of them.
+
+Tests
+~~~~~
+
+In addition to filters there also are tests you can perform using the is
+operator.  Here are some examples::
+
+    {% if user.user_id is odd %}
+        {{ user.username|e }} is odd
+    {% else %}
+        hmm. {{ user.username|e }} looks pretty normal
+    {% endif %}
+
+Loops
+~~~~~
+
+For loops work very similar to Django, the only incompatibility is that in
+Jinja2 the special variable for the loop context is called `loop` and not
+`forloop` like in Django.
+
+Cycle
+~~~~~
+
+The ``{% cycle %}`` tag does not exist in Jinja because of it's implicit
+nature.  However you can achieve mostly the same by using the `cycle`
+method on a loop object.
+
+The following Django template::
+
+    {% for user in users %}
+        <li class="{% cycle 'odd' 'even' %}">{{ user }}</li>
+    {% endfor %}
+
+Would look like this in Jinja::
+
+    {% for user in users %}
+        <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
+    {% endfor %}
+
+There is no equivalent of ``{% cycle ... as variable %}``.
+
+
+Mako
+----
+
+.. highlight:: html+mako
+
+If you have used Mako so far and want to switch to Jinja2 you can configure
+Jinja2 to look more like Mako:
+
+.. sourcecode:: python
+
+    env = Environment('<%', '%>', '${', '}', '%')
+
+Once the environment is configure like that Jinja2 should be able to interpret
+a small subset of Mako templates.  Jinja2 does not support embedded Python code
+so you would have to move that out of the template.  The syntax for defs (in
+Jinja2 defs are called macros) and template inheritance is different too.  The
+following Mako template::
+
+    <%inherit file="layout.html" />
+    <%def name="title()">Page Title</%def>
+    <ul>
+    % for item in list:
+        <li>${item}</li>
+    % endfor
+    </ul>
+
+Looks like this in Jinja2 with the above configuration::
+
+    <% extends "layout.html" %>
+    <% block title %>Page Title<% endblock %>
+    <% block body %>
+    <ul>
+    % for item in list:
+        <li>${item}</li>
+    % endfor
+    </ul>
+    <% endblock %>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst b/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst
new file mode 100644
index 0000000..4a1f6ff
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/templates.rst
@@ -0,0 +1,1365 @@
+Template Designer Documentation
+===============================
+
+.. highlight:: html+jinja
+
+This document describes the syntax and semantics of the template engine and
+will be most useful as reference to those creating Jinja templates.  As the
+template engine is very flexible the configuration from the application might
+be slightly different from here in terms of delimiters and behavior of
+undefined values.
+
+
+Synopsis
+--------
+
+A template is simply a text file.  It can generate any text-based format
+(HTML, XML, CSV, LaTeX, etc.).  It doesn't have a specific extension,
+``.html`` or ``.xml`` are just fine.
+
+A template contains **variables** or **expressions**, which get replaced with
+values when the template is evaluated, and tags, which control the logic of
+the template.  The template syntax is heavily inspired by Django and Python.
+
+Below is a minimal template that illustrates a few basics.  We will cover
+the details later in that document::
+
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+    <html lang="en">
+    <head>
+        <title>My Webpage</title>
+    </head>
+    <body>
+        <ul id="navigation">
+        {% for item in navigation %}
+            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
+        {% endfor %}
+        </ul>
+
+        <h1>My Webpage</h1>
+        {{ a_variable }}
+    </body>
+    </html>
+
+This covers the default settings.  The application developer might have
+changed the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar.
+
+There are two kinds of delimiers. ``{% ... %}`` and ``{{ ... }}``.  The first
+one is used to execute statements such as for-loops or assign values, the
+latter prints the result of the expression to the template.
+
+.. _variables:
+
+Variables
+---------
+
+The application passes variables to the templates you can mess around in the
+template.  Variables may have attributes or elements on them you can access
+too.  How a variable looks like, heavily depends on the application providing
+those.
+
+You can use a dot (``.``) to access attributes of a variable, alternative the
+so-called "subscript" syntax (``[]``) can be used.  The following lines do
+the same::
+
+    {{ foo.bar }}
+    {{ foo['bar'] }}
+
+It's important to know that the curly braces are *not* part of the variable
+but the print statement.  If you access variables inside tags don't put the
+braces around.
+
+If a variable or attribute does not exist you will get back an undefined
+value.  What you can do with that kind of value depends on the application
+configuration, the default behavior is that it evaluates to an empty string
+if printed and that you can iterate over it, but every other operation fails.
+
+.. _notes-on-subscriptions:
+
+.. admonition:: Implementation
+
+    For convenience sake ``foo.bar`` in Jinja2 does the following things on
+    the Python layer:
+
+    -   check if there is an attribute called `bar` on `foo`.
+    -   if there is not, check if there is an item ``'bar'`` in `foo`.
+    -   if there is not, return an undefined object.
+
+    ``foo['bar']`` on the other hand works mostly the same with the a small
+    difference in the order:
+
+    -   check if there is an item ``'bar'`` in `foo`.
+    -   if there is not, check if there is an attribute called `bar` on `foo`.
+    -   if there is not, return an undefined object.
+
+    This is important if an object has an item or attribute with the same
+    name.  Additionally there is the :func:`attr` filter that just looks up
+    attributes.
+
+.. _filters:
+
+Filters
+-------
+
+Variables can by modified by **filters**.  Filters are separated from the
+variable by a pipe symbol (``|``) and may have optional arguments in
+parentheses.  Multiple filters can be chained.  The output of one filter is
+applied to the next.
+
+``{{ name|striptags|title }}`` for example will remove all HTML Tags from the
+`name` and title-cases it.  Filters that accept arguments have parentheses
+around the arguments, like a function call.  This example will join a list
+by commas:  ``{{ list|join(', ') }}``.
+
+The :ref:`builtin-filters` below describes all the builtin filters.
+
+.. _tests:
+
+Tests
+-----
+
+Beside filters there are also so called "tests" available.  Tests can be used
+to test a variable against a common expression.  To test a variable or
+expression you add `is` plus the name of the test after the variable.  For
+example to find out if a variable is defined you can do ``name is defined``
+which will then return true or false depending on if `name` is defined.
+
+Tests can accept arguments too.  If the test only takes one argument you can
+leave out the parentheses to group them.  For example the following two
+expressions do the same::
+
+    {% if loop.index is divisibleby 3 %}
+    {% if loop.index is divisibleby(3) %}
+
+The :ref:`builtin-tests` below describes all the builtin tests.
+
+
+Comments
+--------
+
+To comment-out part of a line in a template, use the comment syntax which is
+by default set to ``{# ... #}``.  This is useful to comment out parts of the
+template for debugging or to add information for other template designers or
+yourself::
+
+    {# note: disabled template because we no longer use this
+        {% for user in users %}
+            ...
+        {% endfor %}
+    #}
+
+
+Whitespace Control
+------------------
+
+In the default configuration whitespace is not further modified by the
+template engine, so each whitespace (spaces, tabs, newlines etc.) is returned
+unchanged.  If the application configures Jinja to `trim_blocks` the first
+newline after a a template tag is removed automatically (like in PHP).
+
+But you can also strip whitespace in templates by hand.  If you put an minus
+sign (``-``) to the start or end of an block (for example a for tag), a
+comment or variable expression you can remove the whitespaces after or before
+that block::
+
+    {% for item in seq -%}
+        {{ item }}
+    {%- endfor %}
+    
+This will yield all elements without whitespace between them.  If `seq` was
+a list of numbers from ``1`` to ``9`` the output would be ``123456789``.
+
+If :ref:`line-statements` are enabled they strip leading whitespace
+automatically up to the beginning of the line.
+
+.. admonition:: Note
+
+    You must not use a whitespace between the tag and the minus sign.
+
+    **valid**::
+
+        {%- if foo -%}...{% endif %}
+
+    **invalid**::
+
+        {% - if foo - %}...{% endif %}
+
+
+Escaping
+--------
+
+It is sometimes desirable or even necessary to have Jinja ignore parts it
+would otherwise handle as variables or blocks.  For example if the default
+syntax is used and you want to use ``{{`` as raw string in the template and
+not start a variable you have to use a trick.
+
+The easiest way is to output the variable delimiter (``{{``) by using a
+variable expression::
+
+    {{ '{{' }}
+
+For bigger sections it makes sense to mark a block `raw`.  For example to
+put Jinja syntax as example into a template you can use this snippet::
+
+    {% raw %}
+        <ul>
+        {% for item in seq %}
+            <li>{{ item }}</li>
+        {% endfor %}
+        </ul>
+    {% endraw %}
+
+
+.. _line-statements:
+
+Line Statements
+---------------
+
+If line statements are enabled by the application it's possible to mark a
+line as a statement.  For example if the line statement prefix is configured
+to ``#`` the following two examples are equivalent::
+
+    <ul>
+    # for item in seq
+        <li>{{ item }}</li>
+    # endfor
+    </ul>
+
+    <ul>
+    {% for item in seq %}
+        <li>{{ item }}</li>
+    {% endfor %}
+    </ul>
+
+The line statement prefix can appear anywhere on the line as long as no text
+precedes it.  For better readability statements that start a block (such as
+`for`, `if`, `elif` etc.) may end with a colon::
+
+    # for item in seq:
+        ...
+    # endfor
+
+
+.. admonition:: Note
+
+    Line statements can span multiple lines if there are open parentheses,
+    braces or brackets::
+
+        <ul>
+        # for href, caption in [('index.html', 'Index'),
+                                ('about.html', 'About')]:
+            <li><a href="{{ href }}">{{ caption }}</a></li>
+        # endfor
+        </ul>
+
+Since Jinja 2.2 line-based comments are available as well.  For example if
+the line-comment prefix is configured to be ``##`` everything from ``##`` to
+the end of the line is ignored (excluding the newline sign)::
+
+    # for item in seq:
+        <li>{{ item }}</li>     ## this comment is ignored
+    # endfor
+
+
+.. _template-inheritance:
+
+Template Inheritance
+--------------------
+
+The most powerful part of Jinja is template inheritance. Template inheritance
+allows you to build a base "skeleton" template that contains all the common
+elements of your site and defines **blocks** that child templates can override.
+
+Sounds complicated but is very basic. It's easiest to understand it by starting
+with an example.
+
+
+Base Template
+~~~~~~~~~~~~~
+
+This template, which we'll call ``base.html``, defines a simple HTML skeleton
+document that you might use for a simple two-column page. It's the job of
+"child" templates to fill the empty blocks with content::
+
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+    <html lang="en">
+    <html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        {% block head %}
+        <link rel="stylesheet" href="style.css" />
+        <title>{% block title %}{% endblock %} - My Webpage</title>
+        {% endblock %}
+    </head>
+    <body>
+        <div id="content">{% block content %}{% endblock %}</div>
+        <div id="footer">
+            {% block footer %}
+            &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
+            {% endblock %}
+        </div>
+    </body>
+
+In this example, the ``{% block %}`` tags define four blocks that child templates
+can fill in. All the `block` tag does is to tell the template engine that a
+child template may override those portions of the template.
+
+Child Template
+~~~~~~~~~~~~~~
+
+A child template might look like this::
+
+    {% extends "base.html" %}
+    {% block title %}Index{% endblock %}
+    {% block head %}
+        {{ super() }}
+        <style type="text/css">
+            .important { color: #336699; }
+        </style>
+    {% endblock %}
+    {% block content %}
+        <h1>Index</h1>
+        <p class="important">
+          Welcome on my awesome homepage.
+        </p>
+    {% endblock %}
+
+The ``{% extends %}`` tag is the key here. It tells the template engine that
+this template "extends" another template.  When the template system evaluates
+this template, first it locates the parent.  The extends tag should be the
+first tag in the template.  Everything before it is printed out normally and
+may cause confusion.  For details about this behavior and how to take
+advantage of it, see :ref:`null-master-fallback`.
+
+The filename of the template depends on the template loader.  For example the
+:class:`FileSystemLoader` allows you to access other templates by giving the
+filename.  You can access templates in subdirectories with an slash::
+
+    {% extends "layout/default.html" %}
+
+But this behavior can depend on the application embedding Jinja.  Note that
+since the child template doesn't define the ``footer`` block, the value from
+the parent template is used instead.
+
+You can't define multiple ``{% block %}`` tags with the same name in the
+same template.  This limitation exists because a block tag works in "both"
+directions.  That is, a block tag doesn't just provide a hole to fill - it
+also defines the content that fills the hole in the *parent*.  If there
+were two similarly-named ``{% block %}`` tags in a template, that template's
+parent wouldn't know which one of the blocks' content to use.
+
+If you want to print a block multiple times you can however use the special
+`self` variable and call the block with that name::
+
+    <title>{% block title %}{% endblock %}</title>
+    <h1>{{ self.title() }}</h1>
+    {% block body %}{% endblock %}
+
+
+Super Blocks
+~~~~~~~~~~~~
+
+It's possible to render the contents of the parent block by calling `super`.
+This gives back the results of the parent block::
+
+    {% block sidebar %}
+        <h3>Table Of Contents</h3>
+        ...
+        {{ super() }}
+    {% endblock %}
+
+
+Named Block End-Tags
+~~~~~~~~~~~~~~~~~~~~
+
+Jinja2 allows you to put the name of the block after the end tag for better
+readability::
+
+    {% block sidebar %}
+        {% block inner_sidebar %}
+            ...
+        {% endblock inner_sidebar %}
+    {% endblock sidebar %}
+
+However the name after the `endblock` word must match the block name.
+
+
+Block Nesting and Scope
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Blocks can be nested for more complex layouts.  However per default blocks
+may not access variables from outer scopes::
+
+    {% for item in seq %}
+        <li>{% block loop_item %}{{ item }}{% endblock %}</li>
+    {% endfor %}
+
+This example would output empty ``<li>`` items because `item` is unavailable
+inside the block.  The reason for this is that if the block is replaced by
+a child template a variable would appear that was not defined in the block or
+passed to the context.
+
+Starting with Jinja 2.2 you can explicitly specify that variables are
+available in a block by setting the block to "scoped" by adding the `scoped`
+modifier to a block declaration::
+
+    {% for item in seq %}
+        <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
+    {% endfor %}
+
+When overriding a block the `scoped` modifier does not have to be provided.
+
+
+Template Objects
+~~~~~~~~~~~~~~~~
+
+.. versionchanged:: 2.4
+
+If a template object was passed to the template context you can
+extend from that object as well.  Assuming the calling code passes
+a layout template as `layout_template` to the environment, this
+code works::
+
+    {% extends layout_template %}
+
+Previously the `layout_template` variable had to be a string with
+the layout template's filename for this to work.
+
+
+HTML Escaping
+-------------
+
+When generating HTML from templates, there's always a risk that a variable will
+include characters that affect the resulting HTML.  There are two approaches:
+manually escaping each variable or automatically escaping everything by default.
+
+Jinja supports both, but what is used depends on the application configuration.
+The default configuaration is no automatic escaping for various reasons:
+
+-   escaping everything except of safe values will also mean that Jinja is
+    escaping variables known to not include HTML such as numbers which is
+    a huge performance hit.
+
+-   The information about the safety of a variable is very fragile.  It could
+    happen that by coercing safe and unsafe values the return value is double
+    escaped HTML.
+
+Working with Manual Escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If manual escaping is enabled it's **your** responsibility to escape
+variables if needed.  What to escape?  If you have a variable that *may*
+include any of the following chars (``>``, ``<``, ``&``, or ``"``) you
+**have to** escape it unless the variable contains well-formed and trusted
+HTML.  Escaping works by piping the variable through the ``|e`` filter:
+``{{ user.username|e }}``.
+
+Working with Automatic Escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When automatic escaping is enabled everything is escaped by default except
+for values explicitly marked as safe.  Those can either be marked by the
+application or in the template by using the `|safe` filter.  The main
+problem with this approach is that Python itself doesn't have the concept
+of tainted values so the information if a value is safe or unsafe can get
+lost.  If the information is lost escaping will take place which means that
+you could end up with double escaped contents.
+
+Double escaping is easy to avoid however, just rely on the tools Jinja2
+provides and don't use builtin Python constructs such as the string modulo
+operator.
+
+Functions returning template data (macros, `super`, `self.BLOCKNAME`) return
+safe markup always.
+
+String literals in templates with automatic escaping are considered unsafe
+too.  The reason for this is that the safe string is an extension to Python
+and not every library will work properly with it.
+
+
+List of Control Structures
+--------------------------
+
+A control structure refers to all those things that control the flow of a
+program - conditionals (i.e. if/elif/else), for-loops, as well as things like
+macros and blocks.  Control structures appear inside ``{% ... %}`` blocks
+in the default syntax.
+
+For
+~~~
+
+Loop over each item in a sequence.  For example, to display a list of users
+provided in a variable called `users`::
+
+    <h1>Members</h1>
+    <ul>
+    {% for user in users %}
+      <li>{{ user.username|e }}</li>
+    {% endfor %}
+    </ul>
+
+Inside of a for loop block you can access some special variables:
+
++-----------------------+---------------------------------------------------+
+| Variable              | Description                                       |
++=======================+===================================================+
+| `loop.index`          | The current iteration of the loop. (1 indexed)    |
++-----------------------+---------------------------------------------------+
+| `loop.index0`         | The current iteration of the loop. (0 indexed)    |
++-----------------------+---------------------------------------------------+
+| `loop.revindex`       | The number of iterations from the end of the loop |
+|                       | (1 indexed)                                       |
++-----------------------+---------------------------------------------------+
+| `loop.revindex0`      | The number of iterations from the end of the loop |
+|                       | (0 indexed)                                       |
++-----------------------+---------------------------------------------------+
+| `loop.first`          | True if first iteration.                          |
++-----------------------+---------------------------------------------------+
+| `loop.last`           | True if last iteration.                           |
++-----------------------+---------------------------------------------------+
+| `loop.length`         | The number of items in the sequence.              |
++-----------------------+---------------------------------------------------+
+| `loop.cycle`          | A helper function to cycle between a list of      |
+|                       | sequences.  See the explanation below.            |
++-----------------------+---------------------------------------------------+
+
+Within a for-loop, it's possible to cycle among a list of strings/variables
+each time through the loop by using the special `loop.cycle` helper::
+
+    {% for row in rows %}
+        <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
+    {% endfor %}
+
+With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound
+cycling.  For more information have a look at the :ref:`builtin-globals`.
+
+.. _loop-filtering:
+
+Unlike in Python it's not possible to `break` or `continue` in a loop.  You
+can however filter the sequence during iteration which allows you to skip
+items.  The following example skips all the users which are hidden::
+
+    {% for user in users if not user.hidden %}
+        <li>{{ user.username|e }}</li>
+    {% endfor %}
+
+The advantage is that the special `loop` variable will count correctly thus
+not counting the users not iterated over.
+
+If no iteration took place because the sequence was empty or the filtering
+removed all the items from the sequence you can render a replacement block
+by using `else`::
+
+    <ul>
+    {% for user in users %}
+        <li>{{ user.username|e }}</li>
+    {% else %}
+        <li><em>no users found</em></li>
+    {% endfor %}
+    </ul>
+
+It is also possible to use loops recursively.  This is useful if you are
+dealing with recursive data such as sitemaps.  To use loops recursively you
+basically have to add the `recursive` modifier to the loop definition and
+call the `loop` variable with the new iterable where you want to recurse.
+
+The following example implements a sitemap with recursive loops::
+
+    <ul class="sitemap">
+    {%- for item in sitemap recursive %}
+        <li><a href="{{ item.href|e }}">{{ item.title }}</a>
+        {%- if item.children -%}
+            <ul class="submenu">{{ loop(item.children) }}</ul>
+        {%- endif %}</li>
+    {%- endfor %}
+    </ul>
+
+
+If
+~~
+
+The `if` statement in Jinja is comparable with the if statements of Python.
+In the simplest form you can use it to test if a variable is defined, not
+empty or not false::
+
+    {% if users %}
+    <ul>
+    {% for user in users %}
+        <li>{{ user.username|e }}</li>
+    {% endfor %}
+    </ul>
+    {% endif %}
+
+For multiple branches `elif` and `else` can be used like in Python.  You can
+use more complex :ref:`expressions` there too::
+
+    {% if kenny.sick %}
+        Kenny is sick.
+    {% elif kenny.dead %}
+        You killed Kenny!  You bastard!!!
+    {% else %}
+        Kenny looks okay --- so far
+    {% endif %}
+
+If can also be used as :ref:`inline expression <if-expression>` and for
+:ref:`loop filtering <loop-filtering>`.
+
+
+Macros
+~~~~~~
+
+Macros are comparable with functions in regular programming languages.  They
+are useful to put often used idioms into reusable functions to not repeat
+yourself.
+
+Here a small example of a macro that renders a form element::
+
+    {% macro input(name, value='', type='text', size=20) -%}
+        <input type="{{ type }}" name="{{ name }}" value="{{
+            value|e }}" size="{{ size }}">
+    {%- endmacro %}
+
+The macro can then be called like a function in the namespace::
+
+    <p>{{ input('username') }}</p>
+    <p>{{ input('password', type='password') }}</p>
+
+If the macro was defined in a different template you have to
+:ref:`import <import>` it first.
+
+Inside macros you have access to three special variables:
+
+`varargs`
+    If more positional arguments are passed to the macro than accepted by the
+    macro they end up in the special `varargs` variable as list of values.
+
+`kwargs`
+    Like `varargs` but for keyword arguments.  All unconsumed keyword
+    arguments are stored in this special variable.
+
+`caller`
+    If the macro was called from a :ref:`call<call>` tag the caller is stored
+    in this variable as macro which can be called.
+
+Macros also expose some of their internal details.  The following attributes
+are available on a macro object:
+
+`name`
+    The name of the macro.  ``{{ input.name }}`` will print ``input``.
+
+`arguments`
+    A tuple of the names of arguments the macro accepts.
+
+`defaults`
+    A tuple of default values.
+
+`catch_kwargs`
+    This is `true` if the macro accepts extra keyword arguments (ie: accesses
+    the special `kwargs` variable).
+
+`catch_varargs`
+    This is `true` if the macro accepts extra positional arguments (ie:
+    accesses the special `varargs` variable).
+
+`caller`
+    This is `true` if the macro accesses the special `caller` variable and may
+    be called from a :ref:`call<call>` tag.
+
+If a macro name starts with an underscore it's not exported and can't
+be imported.
+
+
+.. _call:
+
+Call
+~~~~
+
+In some cases it can be useful to pass a macro to another macro.  For this
+purpose you can use the special `call` block.  The following example shows
+a macro that takes advantage of the call functionality and how it can be
+used::
+
+    {% macro render_dialog(title, class='dialog') -%}
+        <div class="{{ class }}">
+            <h2>{{ title }}</h2>
+            <div class="contents">
+                {{ caller() }}
+            </div>
+        </div>
+    {%- endmacro %}
+
+    {% call render_dialog('Hello World') %}
+        This is a simple dialog rendered by using a macro and
+        a call block.
+    {% endcall %}
+
+It's also possible to pass arguments back to the call block.  This makes it
+useful as replacement for loops.  Generally speaking a call block works
+exactly like an macro, just that it doesn't have a name.
+
+Here an example of how a call block can be used with arguments::
+
+    {% macro dump_users(users) -%}
+        <ul>
+        {%- for user in users %}
+            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+        {%- endfor %}
+        </ul>
+    {%- endmacro %}
+
+    {% call(user) dump_users(list_of_user) %}
+        <dl>
+            <dl>Realname</dl>
+            <dd>{{ user.realname|e }}</dd>
+            <dl>Description</dl>
+            <dd>{{ user.description }}</dd>
+        </dl>
+    {% endcall %}
+
+
+Filters
+~~~~~~~
+
+Filter sections allow you to apply regular Jinja2 filters on a block of
+template data.  Just wrap the code in the special `filter` section::
+
+    {% filter upper %}
+        This text becomes uppercase
+    {% endfilter %}
+
+
+Assignments
+~~~~~~~~~~~
+
+Inside code blocks you can also assign values to variables.  Assignments at
+top level (outside of blocks, macros or loops) are exported from the template
+like top level macros and can be imported by other templates.
+
+Assignments use the `set` tag and can have multiple targets::
+
+    {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
+    {% set key, value = call_something() %}
+
+
+Extends
+~~~~~~~
+
+The `extends` tag can be used to extend a template from another one.  You
+can have multiple of them in a file but only one of them may be executed
+at the time.  See the section about :ref:`template-inheritance` above.
+
+
+Block
+~~~~~
+
+Blocks are used for inheritance and act as placeholders and replacements
+at the same time.  They are documented in detail as part of the section
+about :ref:`template-inheritance`.
+
+
+Include
+~~~~~~~
+
+The `include` statement is useful to include a template and return the
+rendered contents of that file into the current namespace::
+
+    {% include 'header.html' %}
+        Body
+    {% include 'footer.html' %}
+
+Included templates have access to the variables of the active context by
+default.  For more details about context behavior of imports and includes
+see :ref:`import-visibility`.
+
+From Jinja 2.2 onwards you can mark an include with ``ignore missing`` in
+which case Jinja will ignore the statement if the template to be ignored
+does not exist.  When combined with ``with`` or ``without context`` it has
+to be placed *before* the context visibility statement.  Here some valid
+examples::
+
+    {% include "sidebar.html" ignore missing %}
+    {% include "sidebar.html" ignore missing with context %}
+    {% include "sidebar.html" ignore missing without context %}
+
+.. versionadded:: 2.2
+
+You can also provide a list of templates that are checked for existence
+before inclusion.  The first template that exists will be included.  If
+`ignore missing` is given, it will fall back to rendering nothing if
+none of the templates exist, otherwise it will raise an exception.
+
+Example::
+
+    {% include ['page_detailed.html', 'page.html'] %}
+    {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
+
+.. versionchanged:: 2.4
+   If a template object was passed to the template context you can
+   include that object using `include`.
+
+.. _import:
+
+Import
+~~~~~~
+
+Jinja2 supports putting often used code into macros.  These macros can go into
+different templates and get imported from there.  This works similar to the
+import statements in Python.  It's important to know that imports are cached
+and imported templates don't have access to the current template variables,
+just the globals by defualt.  For more details about context behavior of
+imports and includes see :ref:`import-visibility`.
+
+There are two ways to import templates.  You can import the complete template
+into a variable or request specific macros / exported variables from it.
+
+Imagine we have a helper module that renders forms (called `forms.html`)::
+
+    {% macro input(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 %}
+
+The easiest and most flexible is importing the whole module into a variable.
+That way you can access the attributes::
+
+    {% import 'forms.html' as forms %}
+    <dl>
+        <dt>Username</dt>
+        <dd>{{ forms.input('username') }}</dd>
+        <dt>Password</dt>
+        <dd>{{ forms.input('password', type='password') }}</dd>
+    </dl>
+    <p>{{ forms.textarea('comment') }}</p>
+
+
+Alternatively you can import names from the template into the current
+namespace::
+
+    {% from 'forms.html' import input as input_field, textarea %}
+    <dl>
+        <dt>Username</dt>
+        <dd>{{ input_field('username') }}</dd>
+        <dt>Password</dt>
+        <dd>{{ input_field('password', type='password') }}</dd>
+    </dl>
+    <p>{{ textarea('comment') }}</p>
+
+Macros and variables starting with one ore more underscores are private and
+cannot be imported.
+
+.. versionchanged:: 2.4
+   If a template object was passed to the template context you can
+   import from that object.
+
+
+.. _import-visibility:
+
+Import Context Behavior
+-----------------------
+
+Per default included templates are passed the current context and imported
+templates not.  The reason for this is that imports unlike includes are
+cached as imports are often used just as a module that holds macros.
+
+This however can be changed of course explicitly.  By adding `with context`
+or `without context` to the import/include directive the current context
+can be passed to the template and caching is disabled automatically.
+
+Here two examples::
+
+    {% from 'forms.html' import input with context %}
+    {% include 'header.html' without context %}
+
+.. admonition:: Note
+
+    In Jinja 2.0 the context that was passed to the included template
+    did not include variables defined in the template.  As a matter of
+    fact this did not work::
+
+        {% for box in boxes %}
+            {% include "render_box.html" %}
+        {% endfor %}
+
+    The included template ``render_box.html`` is not able to access
+    `box` in Jinja 2.0, but in Jinja 2.1.
+
+
+.. _expressions:
+
+Expressions
+-----------
+
+Jinja allows basic expressions everywhere.  These work very similar to regular
+Python and even if you're not working with Python you should feel comfortable
+with it.
+
+Literals
+~~~~~~~~
+
+The simplest form of expressions are literals.  Literals are representations
+for Python objects such as strings and numbers.  The following literals exist:
+
+"Hello World":
+    Everything between two double or single quotes is a string.  They are
+    useful whenever you need a string in the template (for example as
+    arguments to function calls, filters or just to extend or include a
+    template).
+
+42 / 42.23:
+    Integers and floating point numbers are created by just writing the
+    number down.  If a dot is present the number is a float, otherwise an
+    integer.  Keep in mind that for Python ``42`` and ``42.0`` is something
+    different.
+
+['list', 'of', 'objects']:
+    Everything between two brackets is a list.  Lists are useful to store
+    sequential data in or to iterate over them.  For example you can easily
+    create a list of links using lists and tuples with a for loop::
+
+        <ul>
+        {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
+                                 ('downloads.html', 'Downloads')] %}
+            <li><a href="{{ href }}">{{ caption }}</a></li>
+        {% endfor %}
+        </ul>
+
+('tuple', 'of', 'values'):
+    Tuples are like lists, just that you can't modify them.  If the tuple
+    only has one item you have to end it with a comma.  Tuples are usually
+    used to represent items of two or more elements.  See the example above
+    for more details.
+
+{'dict': 'of', 'key': 'and', 'value': 'pairs'}:
+    A dict in Python is a structure that combines keys and values.  Keys must
+    be unique and always have exactly one value.  Dicts are rarely used in
+    templates, they are useful in some rare cases such as the :func:`xmlattr`
+    filter.
+
+true / false:
+    true is always true and false is always false.
+
+.. admonition:: Note
+
+    The special constants `true`, `false` and `none` are indeed lowercase.
+    Because that caused confusion in the past, when writing `True` expands
+    to an undefined variable that is considered false, all three of them can
+    be written in title case too (`True`, `False`, and `None`).  However for
+    consistency (all Jinja identifiers are lowercase) you should use the
+    lowercase versions.
+
+Math
+~~~~
+
+Jinja allows you to calculate with values.  This is rarely useful in templates
+but exists for completeness' sake.  The following operators are supported:
+
+\+
+    Adds two objects together.  Usually the objects are numbers but if both are
+    strings or lists you can concatenate them this way.  This however is not
+    the preferred way to concatenate strings!  For string concatenation have
+    a look at the ``~`` operator.  ``{{ 1 + 1 }}`` is ``2``.
+
+\-
+    Substract the second number from the first one.  ``{{ 3 - 2 }}`` is ``1``.
+
+/
+    Divide two numbers.  The return value will be a floating point number.
+    ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
+
+//
+    Divide two numbers and return the truncated integer result.
+    ``{{ 20 / 7 }}`` is ``2``.
+
+%
+    Calculate the remainder of an integer division.  ``{{ 11 % 7 }}`` is ``4``.
+
+\*
+    Multiply the left operand with the right one.  ``{{ 2 * 2 }}`` would
+    return ``4``.  This can also be used to repeat a string multiple times.
+    ``{{ '=' * 80 }}`` would print a bar of 80 equal signs.
+
+\**
+    Raise the left operand to the power of the right operand.  ``{{ 2**3 }}``
+    would return ``8``.
+
+Comparisons
+~~~~~~~~~~~
+
+==
+    Compares two objects for equality.
+
+!=
+    Compares two objects for inequality.
+
+>
+    `true` if the left hand side is greater than the right hand side.
+
+>=
+    `true` if the left hand side is greater or equal to the right hand side.
+
+<
+    `true` if the left hand side is lower than the right hand side.
+
+<=
+    `true` if the left hand side is lower or equal to the right hand side.
+
+Logic
+~~~~~
+
+For `if` statements, `for` filtering or `if` expressions it can be useful to
+combine multiple expressions:
+
+and
+    Return true if the left and the right operand is true.
+
+or
+    Return true if the left or the right operand is true.
+
+not
+    negate a statement (see below).
+
+(expr)
+    group an expression.
+
+.. admonition:: Note
+
+    The ``is`` and ``in`` operators support negation using an infix notation
+    too: ``foo is not bar`` and ``foo not in bar`` instead of ``not foo is bar``
+    and ``not foo in bar``.  All other expressions require a prefix notation:
+    ``not (foo and bar).``
+
+
+Other Operators
+~~~~~~~~~~~~~~~
+
+The following operators are very useful but don't fit into any of the other
+two categories:
+
+in
+    Perform sequence / mapping containment test.  Returns true if the left
+    operand is contained in the right.  ``{{ 1 in [1, 2, 3] }}`` would for
+    example return true.
+
+is
+    Performs a :ref:`test <tests>`.
+
+\|
+    Applies a :ref:`filter <filters>`.
+
+~
+    Converts all operands into strings and concatenates them.
+    ``{{ "Hello " ~ name ~ "!" }}`` would return (assuming `name` is
+    ``'John'``) ``Hello John!``.
+
+()
+    Call a callable: ``{{ post.render() }}``.  Inside of the parentheses you
+    can use positional arguments and keyword arguments like in python:
+    ``{{ post.render(user, full=true) }}``.
+
+. / []
+    Get an attribute of an object.  (See :ref:`variables`)
+
+
+.. _if-expression:
+
+If Expression
+~~~~~~~~~~~~~
+
+It is also possible to use inline `if` expressions.  These are useful in some
+situations.  For example you can use this to extend from one template if a
+variable is defined, otherwise from the default layout template::
+
+    {% extends layout_template if layout_template is defined else 'master.html' %}
+
+The general syntax is ``<do something> if <something is true> else <do
+something else>``.
+
+The `else` part is optional.  If not provided the else block implicitly
+evaluates into an undefined object::
+
+    {{ '[%s]' % page.title if page.title }}
+
+
+.. _builtin-filters:
+
+List of Builtin Filters
+-----------------------
+
+.. jinjafilters::
+
+
+.. _builtin-tests:
+
+List of Builtin Tests
+---------------------
+
+.. jinjatests::
+
+.. _builtin-globals:
+
+List of Global Functions
+------------------------
+
+The following functions are available in the global scope by default:
+
+.. function:: range([start,] stop[, step])
+
+    Return a list containing an arithmetic progression of integers.
+    range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
+    When step is given, it specifies the increment (or decrement).
+    For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
+    These are exactly the valid indices for a list of 4 elements.
+
+    This is useful to repeat a template block multiple times for example
+    to fill a list.  Imagine you have 7 users in the list but you want to
+    render three empty items to enforce a height with CSS::
+
+        <ul>
+        {% for user in users %}
+            <li>{{ user.username }}</li>
+        {% endfor %}
+        {% for number in range(10 - users|count) %}
+            <li class="empty"><span>...</span></li>
+        {% endfor %}
+        </ul>
+
+.. function:: lipsum(n=5, html=True, min=20, max=100)
+
+    Generates some lorem ipsum for the template.  Per default five paragraphs
+    with HTML are generated each paragraph between 20 and 100 words.  If html
+    is disabled regular text is returned.  This is useful to generate simple
+    contents for layout testing.
+
+.. function:: dict(\**items)
+
+    A convenient alternative to dict literals.  ``{'foo': 'bar'}`` is the same
+    as ``dict(foo='bar')``.
+
+.. class:: cycler(\*items)
+
+    The cycler allows you to cycle among values similar to how `loop.cycle`
+    works.  Unlike `loop.cycle` however you can use this cycler outside of
+    loops or over multiple loops.
+
+    This is for example very useful if you want to show a list of folders and
+    files, with the folders on top, but both in the same list with alternating
+    row colors.
+
+    The following example shows how `cycler` can be used::
+
+        {% set row_class = cycler('odd', 'even') %}
+        <ul class="browser">
+        {% for folder in folders %}
+          <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
+        {% endfor %}
+        {% for filename in files %}
+          <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
+        {% endfor %}
+        </ul>
+
+    A cycler has the following attributes and methods:
+
+    .. method:: reset()
+
+        Resets the cycle to the first item.
+
+    .. method:: next()
+
+        Goes one item a head and returns the then current item.
+
+    .. attribute:: current
+
+        Returns the current item.
+    
+    **new in Jinja 2.1**
+
+.. class:: joiner(sep=', ')
+
+    A tiny helper that can be use to "join" multiple sections.  A joiner is
+    passed a string and will return that string every time it's calld, except
+    the first time in which situation it returns an empty string.  You can
+    use this to join things::
+
+        {% set pipe = joiner("|") %}
+        {% if categories %} {{ pipe() }}
+            Categories: {{ categories|join(", ") }}
+        {% endif %}
+        {% if author %} {{ pipe() }}
+            Author: {{ author() }}
+        {% endif %}
+        {% if can_edit %} {{ pipe() }}
+            <a href="?action=edit">Edit</a>
+        {% endif %}
+
+    **new in Jinja 2.1**
+
+
+Extensions
+----------
+
+The following sections cover the built-in Jinja2 extensions that may be
+enabled by the application.  The application could also provide further
+extensions not covered by this documentation.  In that case there should
+be a separate document explaining the extensions.
+
+.. _i18n-in-templates:
+
+i18n
+~~~~
+
+If the i18n extension is enabled it's possible to mark parts in the template
+as translatable.  To mark a section as translatable you can use `trans`::
+
+    <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
+
+To translate a template expression --- say, using template filters or just
+accessing an attribute of an object --- you need to bind the expression to a
+name for use within the translation block::
+
+    <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
+
+If you need to bind more than one expression inside a `trans` tag, separate
+the pieces with a comma (``,``)::
+
+    {% trans book_title=book.title, author=author.name %}
+    This is {{ book_title }} by {{ author }}
+    {% endtrans %}
+
+Inside trans tags no statements are allowed, only variable tags are.
+
+To pluralize, specify both the singular and plural forms with the `pluralize`
+tag, which appears between `trans` and `endtrans`::
+
+    {% trans count=list|length %}
+    There is {{ count }} {{ name }} object.
+    {% pluralize %}
+    There are {{ count }} {{ name }} objects.
+    {% endtrans %}
+
+Per default the first variable in a block is used to determine the correct
+singular or plural form.  If that doesn't work out you can specify the name
+which should be used for pluralizing by adding it as parameter to `pluralize`::
+
+    {% trans ..., user_count=users|length %}...
+    {% pluralize user_count %}...{% endtrans %}
+
+It's also possible to translate strings in expressions.  For that purpose
+three functions exist:
+
+_   `gettext`: translate a single string
+-   `ngettext`: translate a pluralizable string
+-   `_`: alias for `gettext`
+
+For example you can print a translated string easily this way::
+
+    {{ _('Hello World!') }}
+
+To use placeholders you can use the `format` filter::
+
+    {{ _('Hello %(user)s!')|format(user=user.username) }}
+
+For multiple placeholders always use keyword arguments to `format` as other
+languages may not use the words in the same order.
+
+.. versionchanged:: 2.5
+
+If newstyle gettext calls are activated (:ref:`newstyle-gettext`), using
+placeholders is a lot easier:
+
+.. sourcecode:: html+jinja
+
+    {{ gettext('Hello World!') }}
+    {{ gettext('Hello %(name)s!', name='World') }}
+    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
+
+Note that the `ngettext` function's format string automatically recieves
+the count as `num` parameter additionally to the regular parameters.
+
+
+Expression Statement
+~~~~~~~~~~~~~~~~~~~~
+
+If the expression-statement extension is loaded a tag called `do` is available
+that works exactly like the regular variable expression (``{{ ... }}``) just
+that it doesn't print anything.  This can be used to modify lists::
+
+    {% do navigation.append('a string') %}
+
+
+Loop Controls
+~~~~~~~~~~~~~
+
+If the application enables the :ref:`loopcontrols-extension` it's possible to
+use `break` and `continue` in loops.  When `break` is reached, the loop is
+terminated, if `continue` is eached the processing is stopped and continues
+with the next iteration.
+
+Here a loop that skips every second item::
+
+    {% for user in users %}
+        {%- if loop.index is even %}{% continue %}{% endif %}
+        ...
+    {% endfor %}
+
+Likewise a look that stops processing after the 10th iteration::
+
+    {% for user in users %}
+        {%- if loop.index >= 10 %}{% break %}{% endif %}
+    {%- endfor %}
+
+
+With Statement
+~~~~~~~~~~~~~~
+
+.. versionadded:: 2.3
+
+If the application enables the :ref:`with-extension` it is possible to
+use the `with` keyword in templates.  This makes it possible to create
+a new inner scope.  Variables set within this scope are not visible
+outside of the scope.
+
+With in a nutshell::
+
+    {% with %}
+        {% set foo = 42 %}
+        {{ foo }}           foo is 42 here
+    {% endwith %}
+    foo is not visible here any longer
+
+Because it is common to set variables at the beginning of the scope
+you can do that within the with statement.  The following two examples
+are equivalent::
+
+    {% with foo = 42 %}
+        {{ foo }}
+    {% endwith %}
+
+    {% with %}
+        {% set foo = 42 %}
+        {{ foo }}
+    {% endwith %}
+
+.. _autoescape-overrides:
+
+Autoescape Extension
+--------------------
+
+.. versionadded:: 2.4
+
+If the application enables the :ref:`autoescape-extension` one can
+activate and deactivate the autoescaping from within the templates.
+
+Example::
+
+    {% autoescape true %}
+        Autoescaping is active within this block
+    {% endautoescape %}
+
+    {% autoescape false %}
+        Autoescaping is inactive within this block
+    {% endautoescape %}
+
+After the `endautoescape` the behavior is reverted to what it was before.

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst b/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst
new file mode 100644
index 0000000..566575e
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/tricks.rst
@@ -0,0 +1,100 @@
+Tips and Tricks
+===============
+
+.. highlight:: html+jinja
+
+This part of the documentation shows some tips and tricks for Jinja2
+templates.
+
+
+.. _null-master-fallback:
+
+Null-Master Fallback
+--------------------
+
+Jinja2 supports dynamic inheritance and does not distinguish between parent
+and child template as long as no `extends` tag is visited.  While this leads
+to the surprising behavior that everything before the first `extends` tag
+including whitespace is printed out instead of being igored, it can be used
+for a neat trick.
+
+Usually child templates extend from one template that adds a basic HTML
+skeleton.  However it's possible put the `extends` tag into an `if` tag to
+only extend from the layout template if the `standalone` variable evaluates
+to false which it does per default if it's not defined.  Additionally a very
+basic skeleton is added to the file so that if it's indeed rendered with
+`standalone` set to `True` a very basic HTML skeleton is added::
+
+    {% if not standalone %}{% extends 'master.html' %}{% endif -%}
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+    <title>{% block title %}The Page Title{% endblock %}</title>
+    <link rel="stylesheet" href="style.css" type="text/css">
+    {% block body %}
+      <p>This is the page body.</p>
+    {% endblock %}
+
+
+Alternating Rows
+----------------
+
+If you want to have different styles for each row of a table or
+list you can use the `cycle` method on the `loop` object::
+
+    <ul>
+    {% for row in rows %}
+      <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
+    {% endfor %}
+    </ul>
+
+`cycle` can take an unlimited amount of strings.  Each time this
+tag is encountered the next item from the list is rendered.
+
+
+Highlighting Active Menu Items
+------------------------------
+
+Often you want to have a navigation bar with an active navigation
+item.  This is really simple to achieve.  Because assignments outside
+of `block`\s in child templates are global and executed before the layout
+template is evaluated it's possible to define the active menu item in the
+child template::
+
+    {% extends "layout.html" %}
+    {% set active_page = "index" %}
+
+The layout template can then access `active_page`.  Additionally it makes
+sense to defined a default for that variable::
+
+    {% set navigation_bar = [
+        ('/', 'index', 'Index'),
+        ('/downloads/', 'downloads', 'Downloads'),
+        ('/about/', 'about', 'About')
+    ] -%}
+    {% set active_page = active_page|default('index') -%}
+    ...
+    <ul id="navigation">
+    {% for href, id, caption in navigation_bar %}
+      <li{% if id == active_page %} class="active"{% endif
+      %}><a href="{{ href|e }}">{{ caption|e }}</a>/li>
+    {% endfor %}
+    </ul>
+    ...
+
+.. _accessing-the-parent-loop:
+
+Accessing the parent Loop
+-------------------------
+
+The special `loop` variable always points to the innermost loop.  If it's
+desired to have access to an outer loop it's possible to alias it::
+
+    <table>
+    {% for row in table %}
+      <tr>
+      {% set rowloop = loop %}
+      {% for cell in row %}
+        <td id="cell-{{ rowloop.index }}-{{ loop.index }}>{{ cell }}</td>
+      {% endfor %}
+      </tr>
+    {% endfor %}
+    </table>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py
new file mode 100644
index 0000000..7ca9683
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/cycle.py
@@ -0,0 +1,13 @@
+from ambari_jinja2 import Environment
+
+
+env = Environment(line_statement_prefix="#", variable_start_string="${", variable_end_string="}")
+
+
+print env.from_string("""\
+<ul>
+# for item in range(10)
+    <li class="${loop.cycle('odd', 'even')}">${item}</li>
+# endfor
+</ul>\
+""").render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py
new file mode 100644
index 0000000..96b8f36
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/debugger.py
@@ -0,0 +1,7 @@
+from ambari_jinja2 import Environment
+from ambari_jinja2.loaders import FileSystemLoader
+
+env = Environment(loader=FileSystemLoader('templates'))
+
+tmpl = env.get_template('broken.html')
+print tmpl.render(seq=[3, 2, 4, 5, 3, 2, 0, 2, 1])

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py
new file mode 100644
index 0000000..10ea11c
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/inheritance.py
@@ -0,0 +1,12 @@
+from ambari_jinja2 import Environment
+from ambari_jinja2.loaders import DictLoader
+
+
+env = Environment(loader=DictLoader({
+'a': '''[A[{% block body %}{% endblock %}]]''',
+'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''',
+'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}'''
+}))
+
+
+print env.get_template('c').render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html b/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html
new file mode 100644
index 0000000..294d5c9
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/broken.html
@@ -0,0 +1,6 @@
+{% from 'subbroken.html' import may_break %}
+<ul>
+{% for item in seq %}
+  <li>{{ may_break(item) }}</li>
+{% endfor %}
+</ul>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html b/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html
new file mode 100644
index 0000000..245eb7e
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/templates/subbroken.html
@@ -0,0 +1,3 @@
+{% macro may_break(item) -%}
+  [{{ item / 0 }}]
+{%- endmacro %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py
new file mode 100644
index 0000000..721c960
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test.py
@@ -0,0 +1,27 @@
+from ambari_jinja2 import Environment
+from ambari_jinja2.loaders import DictLoader
+
+env = Environment(loader=DictLoader({
+'child.html': u'''\
+{% extends master_layout or 'master.html' %}
+{% include helpers = 'helpers.html' %}
+{% macro get_the_answer() %}42{% endmacro %}
+{% title = 'Hello World' %}
+{% block body %}
+    {{ get_the_answer() }}
+    {{ helpers.conspirate() }}
+{% endblock %}
+''',
+'master.html': u'''\
+<!doctype html>
+<title>{{ title }}</title>
+{% block body %}{% endblock %}
+''',
+'helpers.html': u'''\
+{% macro conspirate() %}23{% endmacro %}
+'''
+}))
+
+
+tmpl = env.get_template("child.html")
+print tmpl.render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py
new file mode 100644
index 0000000..975f74c
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_filter_and_linestatements.py
@@ -0,0 +1,25 @@
+from ambari_jinja2 import Environment
+
+
+env = Environment(line_statement_prefix='%', variable_start_string="${", variable_end_string="}")
+tmpl = env.from_string("""\
+% macro foo()
+    ${caller(42)}
+% endmacro
+<ul>
+% for item in seq
+    <li>${item}</li>
+% endfor
+</ul>
+% call(var) foo()
+    [${var}]
+% endcall
+% filter escape
+    <hello world>
+    % for item in [1, 2, 3]
+      -  ${item}
+    % endfor
+% endfilter
+""")
+
+print tmpl.render(seq=range(10))

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py
new file mode 100644
index 0000000..051ca42
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/test_loop_filter.py
@@ -0,0 +1,12 @@
+from ambari_jinja2 import Environment
+
+tmpl = Environment().from_string("""\
+<ul>
+{%- for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if item % 2 == 0 %}
+    <li>{{ loop.index }} / {{ loop.length }}: {{ item }}</li>
+{%- endfor %}
+</ul>
+if condition: {{ 1 if foo else 0 }}
+""")
+
+print tmpl.render(foo=True)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py b/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py
new file mode 100644
index 0000000..7bada71
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/basic/translate.py
@@ -0,0 +1,6 @@
+from ambari_jinja2 import Environment
+
+print Environment(extensions=['ambari_jinja2.i18n.TransExtension']).from_string("""\
+{% trans %}Hello {{ user }}!{% endtrans %}
+{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
+""").render(user="someone")


[33/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/filters.py b/ambari-common/src/main/python/jinja2/jinja2/filters.py
deleted file mode 100644
index d1848e4..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/filters.py
+++ /dev/null
@@ -1,719 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.filters
-    ~~~~~~~~~~~~~~
-
-    Bundled jinja filters.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import math
-from random import choice
-from operator import itemgetter
-from itertools import imap, groupby
-from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
-from jinja2.runtime import Undefined
-from jinja2.exceptions import FilterArgumentError, SecurityError
-
-
-_word_re = re.compile(r'\w+(?u)')
-
-
-def contextfilter(f):
-    """Decorator for marking context dependent filters. The current
-    :class:`Context` will be passed as first argument.
-    """
-    f.contextfilter = True
-    return f
-
-
-def evalcontextfilter(f):
-    """Decorator for marking eval-context dependent filters.  An eval
-    context object is passed as first argument.  For more information
-    about the eval context, see :ref:`eval-context`.
-
-    .. versionadded:: 2.4
-    """
-    f.evalcontextfilter = True
-    return f
-
-
-def environmentfilter(f):
-    """Decorator for marking evironment dependent filters.  The current
-    :class:`Environment` is passed to the filter as first argument.
-    """
-    f.environmentfilter = True
-    return f
-
-
-def do_forceescape(value):
-    """Enforce HTML escaping.  This will probably double escape variables."""
-    if hasattr(value, '__html__'):
-        value = value.__html__()
-    return escape(unicode(value))
-
-
-@evalcontextfilter
-def do_replace(eval_ctx, s, old, new, count=None):
-    """Return a copy of the value with all occurrences of a substring
-    replaced with a new one. The first argument is the substring
-    that should be replaced, the second is the replacement string.
-    If the optional third argument ``count`` is given, only the first
-    ``count`` occurrences are replaced:
-
-    .. sourcecode:: jinja
-
-        {{ "Hello World"|replace("Hello", "Goodbye") }}
-            -> Goodbye World
-
-        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
-            -> d'oh, d'oh, aaargh
-    """
-    if count is None:
-        count = -1
-    if not eval_ctx.autoescape:
-        return unicode(s).replace(unicode(old), unicode(new), count)
-    if hasattr(old, '__html__') or hasattr(new, '__html__') and \
-       not hasattr(s, '__html__'):
-        s = escape(s)
-    else:
-        s = soft_unicode(s)
-    return s.replace(soft_unicode(old), soft_unicode(new), count)
-
-
-def do_upper(s):
-    """Convert a value to uppercase."""
-    return soft_unicode(s).upper()
-
-
-def do_lower(s):
-    """Convert a value to lowercase."""
-    return soft_unicode(s).lower()
-
-
-@evalcontextfilter
-def do_xmlattr(_eval_ctx, d, autospace=True):
-    """Create an SGML/XML attribute string based on the items in a dict.
-    All values that are neither `none` nor `undefined` are automatically
-    escaped:
-
-    .. sourcecode:: html+jinja
-
-        <ul{{ {'class': 'my_list', 'missing': none,
-                'id': 'list-%d'|format(variable)}|xmlattr }}>
-        ...
-        </ul>
-
-    Results in something like this:
-
-    .. sourcecode:: html
-
-        <ul class="my_list" id="list-42">
-        ...
-        </ul>
-
-    As you can see it automatically prepends a space in front of the item
-    if the filter returned something unless the second parameter is false.
-    """
-    rv = u' '.join(
-        u'%s="%s"' % (escape(key), escape(value))
-        for key, value in d.iteritems()
-        if value is not None and not isinstance(value, Undefined)
-    )
-    if autospace and rv:
-        rv = u' ' + rv
-    if _eval_ctx.autoescape:
-        rv = Markup(rv)
-    return rv
-
-
-def do_capitalize(s):
-    """Capitalize a value. The first character will be uppercase, all others
-    lowercase.
-    """
-    return soft_unicode(s).capitalize()
-
-
-def do_title(s):
-    """Return a titlecased version of the value. I.e. words will start with
-    uppercase letters, all remaining characters are lowercase.
-    """
-    return soft_unicode(s).title()
-
-
-def do_dictsort(value, case_sensitive=False, by='key'):
-    """Sort a dict and yield (key, value) pairs. Because python dicts are
-    unsorted you may want to use this function to order them by either
-    key or value:
-
-    .. sourcecode:: jinja
-
-        {% for item in mydict|dictsort %}
-            sort the dict by key, case insensitive
-
-        {% for item in mydict|dicsort(true) %}
-            sort the dict by key, case sensitive
-
-        {% for item in mydict|dictsort(false, 'value') %}
-            sort the dict by key, case insensitive, sorted
-            normally and ordered by value.
-    """
-    if by == 'key':
-        pos = 0
-    elif by == 'value':
-        pos = 1
-    else:
-        raise FilterArgumentError('You can only sort by either '
-                                  '"key" or "value"')
-    def sort_func(item):
-        value = item[pos]
-        if isinstance(value, basestring) and not case_sensitive:
-            value = value.lower()
-        return value
-
-    return sorted(value.items(), key=sort_func)
-
-
-def do_sort(value, reverse=False, case_sensitive=False):
-    """Sort an iterable.  Per default it sorts ascending, if you pass it
-    true as first argument it will reverse the sorting.
-
-    If the iterable is made of strings the third parameter can be used to
-    control the case sensitiveness of the comparison which is disabled by
-    default.
-
-    .. sourcecode:: jinja
-
-        {% for item in iterable|sort %}
-            ...
-        {% endfor %}
-    """
-    if not case_sensitive:
-        def sort_func(item):
-            if isinstance(item, basestring):
-                item = item.lower()
-            return item
-    else:
-        sort_func = None
-    return sorted(value, key=sort_func, reverse=reverse)
-
-
-def do_default(value, default_value=u'', boolean=False):
-    """If the value is undefined it will return the passed default value,
-    otherwise the value of the variable:
-
-    .. sourcecode:: jinja
-
-        {{ my_variable|default('my_variable is not defined') }}
-
-    This will output the value of ``my_variable`` if the variable was
-    defined, otherwise ``'my_variable is not defined'``. If you want
-    to use default with variables that evaluate to false you have to
-    set the second parameter to `true`:
-
-    .. sourcecode:: jinja
-
-        {{ ''|default('the string was empty', true) }}
-    """
-    if (boolean and not value) or isinstance(value, Undefined):
-        return default_value
-    return value
-
-
-@evalcontextfilter
-def do_join(eval_ctx, value, d=u''):
-    """Return a string which is the concatenation of the strings in the
-    sequence. The separator between elements is an empty string per
-    default, you can define it with the optional parameter:
-
-    .. sourcecode:: jinja
-
-        {{ [1, 2, 3]|join('|') }}
-            -> 1|2|3
-
-        {{ [1, 2, 3]|join }}
-            -> 123
-    """
-    # no automatic escaping?  joining is a lot eaiser then
-    if not eval_ctx.autoescape:
-        return unicode(d).join(imap(unicode, value))
-
-    # if the delimiter doesn't have an html representation we check
-    # if any of the items has.  If yes we do a coercion to Markup
-    if not hasattr(d, '__html__'):
-        value = list(value)
-        do_escape = False
-        for idx, item in enumerate(value):
-            if hasattr(item, '__html__'):
-                do_escape = True
-            else:
-                value[idx] = unicode(item)
-        if do_escape:
-            d = escape(d)
-        else:
-            d = unicode(d)
-        return d.join(value)
-
-    # no html involved, to normal joining
-    return soft_unicode(d).join(imap(soft_unicode, value))
-
-
-def do_center(value, width=80):
-    """Centers the value in a field of a given width."""
-    return unicode(value).center(width)
-
-
-@environmentfilter
-def do_first(environment, seq):
-    """Return the first item of a sequence."""
-    try:
-        return iter(seq).next()
-    except StopIteration:
-        return environment.undefined('No first item, sequence was empty.')
-
-
-@environmentfilter
-def do_last(environment, seq):
-    """Return the last item of a sequence."""
-    try:
-        return iter(reversed(seq)).next()
-    except StopIteration:
-        return environment.undefined('No last item, sequence was empty.')
-
-
-@environmentfilter
-def do_random(environment, seq):
-    """Return a random item from the sequence."""
-    try:
-        return choice(seq)
-    except IndexError:
-        return environment.undefined('No random item, sequence was empty.')
-
-
-def do_filesizeformat(value, binary=False):
-    """Format the value like a 'human-readable' file size (i.e. 13 KB,
-    4.1 MB, 102 bytes, etc).  Per default decimal prefixes are used (mega,
-    giga, etc.), if the second parameter is set to `True` the binary
-    prefixes are used (mebi, gibi).
-    """
-    bytes = float(value)
-    base = binary and 1024 or 1000
-    middle = binary and 'i' or ''
-    if bytes < base:
-        return "%d Byte%s" % (bytes, bytes != 1 and 's' or '')
-    elif bytes < base * base:
-        return "%.1f K%sB" % (bytes / base, middle)
-    elif bytes < base * base * base:
-        return "%.1f M%sB" % (bytes / (base * base), middle)
-    return "%.1f G%sB" % (bytes / (base * base * base), middle)
-
-
-def do_pprint(value, verbose=False):
-    """Pretty print a variable. Useful for debugging.
-
-    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
-    is truthy the output will be more verbose (this requires `pretty`)
-    """
-    return pformat(value, verbose=verbose)
-
-
-@evalcontextfilter
-def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
-    """Converts URLs in plain text into clickable links.
-
-    If you pass the filter an additional integer it will shorten the urls
-    to that number. Also a third argument exists that makes the urls
-    "nofollow":
-
-    .. sourcecode:: jinja
-
-        {{ mytext|urlize(40, true) }}
-            links are shortened to 40 chars and defined with rel="nofollow"
-    """
-    rv = urlize(value, trim_url_limit, nofollow)
-    if eval_ctx.autoescape:
-        rv = Markup(rv)
-    return rv
-
-
-def do_indent(s, width=4, indentfirst=False):
-    """Return a copy of the passed string, each line indented by
-    4 spaces. The first line is not indented. If you want to
-    change the number of spaces or indent the first line too
-    you can pass additional parameters to the filter:
-
-    .. sourcecode:: jinja
-
-        {{ mytext|indent(2, true) }}
-            indent by two spaces and indent the first line too.
-    """
-    indention = u' ' * width
-    rv = (u'\n' + indention).join(s.splitlines())
-    if indentfirst:
-        rv = indention + rv
-    return rv
-
-
-def do_truncate(s, length=255, killwords=False, end='...'):
-    """Return a truncated copy of the string. The length is specified
-    with the first parameter which defaults to ``255``. If the second
-    parameter is ``true`` the filter will cut the text at length. Otherwise
-    it will try to save the last word. If the text was in fact
-    truncated it will append an ellipsis sign (``"..."``). If you want a
-    different ellipsis sign than ``"..."`` you can specify it using the
-    third parameter.
-
-    .. sourcecode jinja::
-
-        {{ mytext|truncate(300, false, '&raquo;') }}
-            truncate mytext to 300 chars, don't split up words, use a
-            right pointing double arrow as ellipsis sign.
-    """
-    if len(s) <= length:
-        return s
-    elif killwords:
-        return s[:length] + end
-    words = s.split(' ')
-    result = []
-    m = 0
-    for word in words:
-        m += len(word) + 1
-        if m > length:
-            break
-        result.append(word)
-    result.append(end)
-    return u' '.join(result)
-
-
-def do_wordwrap(s, width=79, break_long_words=True):
-    """
-    Return a copy of the string passed to the filter wrapped after
-    ``79`` characters.  You can override this default using the first
-    parameter.  If you set the second parameter to `false` Jinja will not
-    split words apart if they are longer than `width`.
-    """
-    import textwrap
-    return u'\n'.join(textwrap.wrap(s, width=width, expand_tabs=False,
-                                   replace_whitespace=False,
-                                   break_long_words=break_long_words))
-
-
-def do_wordcount(s):
-    """Count the words in that string."""
-    return len(_word_re.findall(s))
-
-
-def do_int(value, default=0):
-    """Convert the value into an integer. If the
-    conversion doesn't work it will return ``0``. You can
-    override this default using the first parameter.
-    """
-    try:
-        return int(value)
-    except (TypeError, ValueError):
-        # this quirk is necessary so that "42.23"|int gives 42.
-        try:
-            return int(float(value))
-        except (TypeError, ValueError):
-            return default
-
-
-def do_float(value, default=0.0):
-    """Convert the value into a floating point number. If the
-    conversion doesn't work it will return ``0.0``. You can
-    override this default using the first parameter.
-    """
-    try:
-        return float(value)
-    except (TypeError, ValueError):
-        return default
-
-
-def do_format(value, *args, **kwargs):
-    """
-    Apply python string formatting on an object:
-
-    .. sourcecode:: jinja
-
-        {{ "%s - %s"|format("Hello?", "Foo!") }}
-            -> Hello? - Foo!
-    """
-    if args and kwargs:
-        raise FilterArgumentError('can\'t handle positional and keyword '
-                                  'arguments at the same time')
-    return soft_unicode(value) % (kwargs or args)
-
-
-def do_trim(value):
-    """Strip leading and trailing whitespace."""
-    return soft_unicode(value).strip()
-
-
-def do_striptags(value):
-    """Strip SGML/XML tags and replace adjacent whitespace by one space.
-    """
-    if hasattr(value, '__html__'):
-        value = value.__html__()
-    return Markup(unicode(value)).striptags()
-
-
-def do_slice(value, slices, fill_with=None):
-    """Slice an iterator and return a list of lists containing
-    those items. Useful if you want to create a div containing
-    three ul tags that represent columns:
-
-    .. sourcecode:: html+jinja
-
-        <div class="columwrapper">
-          {%- for column in items|slice(3) %}
-            <ul class="column-{{ loop.index }}">
-            {%- for item in column %}
-              <li>{{ item }}</li>
-            {%- endfor %}
-            </ul>
-          {%- endfor %}
-        </div>
-
-    If you pass it a second argument it's used to fill missing
-    values on the last iteration.
-    """
-    seq = list(value)
-    length = len(seq)
-    items_per_slice = length // slices
-    slices_with_extra = length % slices
-    offset = 0
-    for slice_number in xrange(slices):
-        start = offset + slice_number * items_per_slice
-        if slice_number < slices_with_extra:
-            offset += 1
-        end = offset + (slice_number + 1) * items_per_slice
-        tmp = seq[start:end]
-        if fill_with is not None and slice_number >= slices_with_extra:
-            tmp.append(fill_with)
-        yield tmp
-
-
-def do_batch(value, linecount, fill_with=None):
-    """
-    A filter that batches items. It works pretty much like `slice`
-    just the other way round. It returns a list of lists with the
-    given number of items. If you provide a second parameter this
-    is used to fill missing items. See this example:
-
-    .. sourcecode:: html+jinja
-
-        <table>
-        {%- for row in items|batch(3, '&nbsp;') %}
-          <tr>
-          {%- for column in row %}
-            <td>{{ column }}</td>
-          {%- endfor %}
-          </tr>
-        {%- endfor %}
-        </table>
-    """
-    result = []
-    tmp = []
-    for item in value:
-        if len(tmp) == linecount:
-            yield tmp
-            tmp = []
-        tmp.append(item)
-    if tmp:
-        if fill_with is not None and len(tmp) < linecount:
-            tmp += [fill_with] * (linecount - len(tmp))
-        yield tmp
-
-
-def do_round(value, precision=0, method='common'):
-    """Round the number to a given precision. The first
-    parameter specifies the precision (default is ``0``), the
-    second the rounding method:
-
-    - ``'common'`` rounds either up or down
-    - ``'ceil'`` always rounds up
-    - ``'floor'`` always rounds down
-
-    If you don't specify a method ``'common'`` is used.
-
-    .. sourcecode:: jinja
-
-        {{ 42.55|round }}
-            -> 43.0
-        {{ 42.55|round(1, 'floor') }}
-            -> 42.5
-
-    Note that even if rounded to 0 precision, a float is returned.  If
-    you need a real integer, pipe it through `int`:
-
-    .. sourcecode:: jinja
-
-        {{ 42.55|round|int }}
-            -> 43
-    """
-    if not method in ('common', 'ceil', 'floor'):
-        raise FilterArgumentError('method must be common, ceil or floor')
-    if method == 'common':
-        return round(value, precision)
-    func = getattr(math, method)
-    return func(value * (10 ** precision)) / (10 ** precision)
-
-
-@environmentfilter
-def do_groupby(environment, value, attribute):
-    """Group a sequence of objects by a common attribute.
-
-    If you for example have a list of dicts or objects that represent persons
-    with `gender`, `first_name` and `last_name` attributes and you want to
-    group all users by genders you can do something like the following
-    snippet:
-
-    .. sourcecode:: html+jinja
-
-        <ul>
-        {% for group in persons|groupby('gender') %}
-            <li>{{ group.grouper }}<ul>
-            {% for person in group.list %}
-                <li>{{ person.first_name }} {{ person.last_name }}</li>
-            {% endfor %}</ul></li>
-        {% endfor %}
-        </ul>
-
-    Additionally it's possible to use tuple unpacking for the grouper and
-    list:
-
-    .. sourcecode:: html+jinja
-
-        <ul>
-        {% for grouper, list in persons|groupby('gender') %}
-            ...
-        {% endfor %}
-        </ul>
-
-    As you can see the item we're grouping by is stored in the `grouper`
-    attribute and the `list` contains all the objects that have this grouper
-    in common.
-    """
-    expr = lambda x: environment.getitem(x, attribute)
-    return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
-
-
-class _GroupTuple(tuple):
-    __slots__ = ()
-    grouper = property(itemgetter(0))
-    list = property(itemgetter(1))
-
-    def __new__(cls, (key, value)):
-        return tuple.__new__(cls, (key, list(value)))
-
-
-def do_list(value):
-    """Convert the value into a list.  If it was a string the returned list
-    will be a list of characters.
-    """
-    return list(value)
-
-
-def do_mark_safe(value):
-    """Mark the value as safe which means that in an environment with automatic
-    escaping enabled this variable will not be escaped.
-    """
-    return Markup(value)
-
-
-def do_mark_unsafe(value):
-    """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
-    return unicode(value)
-
-
-def do_reverse(value):
-    """Reverse the object or return an iterator the iterates over it the other
-    way round.
-    """
-    if isinstance(value, basestring):
-        return value[::-1]
-    try:
-        return reversed(value)
-    except TypeError:
-        try:
-            rv = list(value)
-            rv.reverse()
-            return rv
-        except TypeError:
-            raise FilterArgumentError('argument must be iterable')
-
-
-@environmentfilter
-def do_attr(environment, obj, name):
-    """Get an attribute of an object.  ``foo|attr("bar")`` works like
-    ``foo["bar"]`` just that always an attribute is returned and items are not
-    looked up.
-
-    See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
-    """
-    try:
-        name = str(name)
-    except UnicodeError:
-        pass
-    else:
-        try:
-            value = getattr(obj, name)
-        except AttributeError:
-            pass
-        else:
-            if environment.sandboxed and not \
-               environment.is_safe_attribute(obj, name, value):
-                return environment.unsafe_undefined(obj, name)
-            return value
-    return environment.undefined(obj=obj, name=name)
-
-
-FILTERS = {
-    'attr':                 do_attr,
-    'replace':              do_replace,
-    'upper':                do_upper,
-    'lower':                do_lower,
-    'escape':               escape,
-    'e':                    escape,
-    'forceescape':          do_forceescape,
-    'capitalize':           do_capitalize,
-    'title':                do_title,
-    'default':              do_default,
-    'd':                    do_default,
-    'join':                 do_join,
-    'count':                len,
-    'dictsort':             do_dictsort,
-    'sort':                 do_sort,
-    'length':               len,
-    'reverse':              do_reverse,
-    'center':               do_center,
-    'indent':               do_indent,
-    'title':                do_title,
-    'capitalize':           do_capitalize,
-    'first':                do_first,
-    'last':                 do_last,
-    'random':               do_random,
-    'filesizeformat':       do_filesizeformat,
-    'pprint':               do_pprint,
-    'truncate':             do_truncate,
-    'wordwrap':             do_wordwrap,
-    'wordcount':            do_wordcount,
-    'int':                  do_int,
-    'float':                do_float,
-    'string':               soft_unicode,
-    'list':                 do_list,
-    'urlize':               do_urlize,
-    'format':               do_format,
-    'trim':                 do_trim,
-    'striptags':            do_striptags,
-    'slice':                do_slice,
-    'batch':                do_batch,
-    'sum':                  sum,
-    'abs':                  abs,
-    'round':                do_round,
-    'groupby':              do_groupby,
-    'safe':                 do_mark_safe,
-    'xmlattr':              do_xmlattr
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/lexer.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/lexer.py b/ambari-common/src/main/python/jinja2/jinja2/lexer.py
deleted file mode 100644
index 0d3f696..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/lexer.py
+++ /dev/null
@@ -1,681 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.lexer
-    ~~~~~~~~~~~~
-
-    This module implements a Jinja / Python combination lexer. The
-    `Lexer` class provided by this module is used to do some preprocessing
-    for Jinja.
-
-    On the one hand it filters out invalid operators like the bitshift
-    operators we don't allow in templates. On the other hand it separates
-    template code and python code in expressions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-from operator import itemgetter
-from collections import deque
-from jinja2.exceptions import TemplateSyntaxError
-from jinja2.utils import LRUCache, next
-
-
-# cache for the lexers. Exists in order to be able to have multiple
-# environments with the same lexer
-_lexer_cache = LRUCache(50)
-
-# static regular expressions
-whitespace_re = re.compile(r'\s+', re.U)
-string_re = re.compile(r"('([^'\\]*(?:\\.[^'\\]*)*)'"
-                       r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
-integer_re = re.compile(r'\d+')
-
-# we use the unicode identifier rule if this python version is able
-# to handle unicode identifiers, otherwise the standard ASCII one.
-try:
-    compile('föö', '<unknown>', 'eval')
-except SyntaxError:
-    name_re = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b')
-else:
-    from jinja2 import _stringdefs
-    name_re = re.compile(r'[%s][%s]*' % (_stringdefs.xid_start,
-                                         _stringdefs.xid_continue))
-
-float_re = re.compile(r'(?<!\.)\d+\.\d+')
-newline_re = re.compile(r'(\r\n|\r|\n)')
-
-# internal the tokens and keep references to them
-TOKEN_ADD = intern('add')
-TOKEN_ASSIGN = intern('assign')
-TOKEN_COLON = intern('colon')
-TOKEN_COMMA = intern('comma')
-TOKEN_DIV = intern('div')
-TOKEN_DOT = intern('dot')
-TOKEN_EQ = intern('eq')
-TOKEN_FLOORDIV = intern('floordiv')
-TOKEN_GT = intern('gt')
-TOKEN_GTEQ = intern('gteq')
-TOKEN_LBRACE = intern('lbrace')
-TOKEN_LBRACKET = intern('lbracket')
-TOKEN_LPAREN = intern('lparen')
-TOKEN_LT = intern('lt')
-TOKEN_LTEQ = intern('lteq')
-TOKEN_MOD = intern('mod')
-TOKEN_MUL = intern('mul')
-TOKEN_NE = intern('ne')
-TOKEN_PIPE = intern('pipe')
-TOKEN_POW = intern('pow')
-TOKEN_RBRACE = intern('rbrace')
-TOKEN_RBRACKET = intern('rbracket')
-TOKEN_RPAREN = intern('rparen')
-TOKEN_SEMICOLON = intern('semicolon')
-TOKEN_SUB = intern('sub')
-TOKEN_TILDE = intern('tilde')
-TOKEN_WHITESPACE = intern('whitespace')
-TOKEN_FLOAT = intern('float')
-TOKEN_INTEGER = intern('integer')
-TOKEN_NAME = intern('name')
-TOKEN_STRING = intern('string')
-TOKEN_OPERATOR = intern('operator')
-TOKEN_BLOCK_BEGIN = intern('block_begin')
-TOKEN_BLOCK_END = intern('block_end')
-TOKEN_VARIABLE_BEGIN = intern('variable_begin')
-TOKEN_VARIABLE_END = intern('variable_end')
-TOKEN_RAW_BEGIN = intern('raw_begin')
-TOKEN_RAW_END = intern('raw_end')
-TOKEN_COMMENT_BEGIN = intern('comment_begin')
-TOKEN_COMMENT_END = intern('comment_end')
-TOKEN_COMMENT = intern('comment')
-TOKEN_LINESTATEMENT_BEGIN = intern('linestatement_begin')
-TOKEN_LINESTATEMENT_END = intern('linestatement_end')
-TOKEN_LINECOMMENT_BEGIN = intern('linecomment_begin')
-TOKEN_LINECOMMENT_END = intern('linecomment_end')
-TOKEN_LINECOMMENT = intern('linecomment')
-TOKEN_DATA = intern('data')
-TOKEN_INITIAL = intern('initial')
-TOKEN_EOF = intern('eof')
-
-# bind operators to token types
-operators = {
-    '+':            TOKEN_ADD,
-    '-':            TOKEN_SUB,
-    '/':            TOKEN_DIV,
-    '//':           TOKEN_FLOORDIV,
-    '*':            TOKEN_MUL,
-    '%':            TOKEN_MOD,
-    '**':           TOKEN_POW,
-    '~':            TOKEN_TILDE,
-    '[':            TOKEN_LBRACKET,
-    ']':            TOKEN_RBRACKET,
-    '(':            TOKEN_LPAREN,
-    ')':            TOKEN_RPAREN,
-    '{':            TOKEN_LBRACE,
-    '}':            TOKEN_RBRACE,
-    '==':           TOKEN_EQ,
-    '!=':           TOKEN_NE,
-    '>':            TOKEN_GT,
-    '>=':           TOKEN_GTEQ,
-    '<':            TOKEN_LT,
-    '<=':           TOKEN_LTEQ,
-    '=':            TOKEN_ASSIGN,
-    '.':            TOKEN_DOT,
-    ':':            TOKEN_COLON,
-    '|':            TOKEN_PIPE,
-    ',':            TOKEN_COMMA,
-    ';':            TOKEN_SEMICOLON
-}
-
-reverse_operators = dict([(v, k) for k, v in operators.iteritems()])
-assert len(operators) == len(reverse_operators), 'operators dropped'
-operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
-                         sorted(operators, key=lambda x: -len(x))))
-
-ignored_tokens = frozenset([TOKEN_COMMENT_BEGIN, TOKEN_COMMENT,
-                            TOKEN_COMMENT_END, TOKEN_WHITESPACE,
-                            TOKEN_WHITESPACE, TOKEN_LINECOMMENT_BEGIN,
-                            TOKEN_LINECOMMENT_END, TOKEN_LINECOMMENT])
-ignore_if_empty = frozenset([TOKEN_WHITESPACE, TOKEN_DATA,
-                             TOKEN_COMMENT, TOKEN_LINECOMMENT])
-
-
-def _describe_token_type(token_type):
-    if token_type in reverse_operators:
-        return reverse_operators[token_type]
-    return {
-        TOKEN_COMMENT_BEGIN:        'begin of comment',
-        TOKEN_COMMENT_END:          'end of comment',
-        TOKEN_COMMENT:              'comment',
-        TOKEN_LINECOMMENT:          'comment',
-        TOKEN_BLOCK_BEGIN:          'begin of statement block',
-        TOKEN_BLOCK_END:            'end of statement block',
-        TOKEN_VARIABLE_BEGIN:       'begin of print statement',
-        TOKEN_VARIABLE_END:         'end of print statement',
-        TOKEN_LINESTATEMENT_BEGIN:  'begin of line statement',
-        TOKEN_LINESTATEMENT_END:    'end of line statement',
-        TOKEN_DATA:                 'template data / text',
-        TOKEN_EOF:                  'end of template'
-    }.get(token_type, token_type)
-
-
-def describe_token(token):
-    """Returns a description of the token."""
-    if token.type == 'name':
-        return token.value
-    return _describe_token_type(token.type)
-
-
-def describe_token_expr(expr):
-    """Like `describe_token` but for token expressions."""
-    if ':' in expr:
-        type, value = expr.split(':', 1)
-        if type == 'name':
-            return value
-    else:
-        type = expr
-    return _describe_token_type(type)
-
-
-def count_newlines(value):
-    """Count the number of newline characters in the string.  This is
-    useful for extensions that filter a stream.
-    """
-    return len(newline_re.findall(value))
-
-
-def compile_rules(environment):
-    """Compiles all the rules from the environment into a list of rules."""
-    e = re.escape
-    rules = [
-        (len(environment.comment_start_string), 'comment',
-         e(environment.comment_start_string)),
-        (len(environment.block_start_string), 'block',
-         e(environment.block_start_string)),
-        (len(environment.variable_start_string), 'variable',
-         e(environment.variable_start_string))
-    ]
-
-    if environment.line_statement_prefix is not None:
-        rules.append((len(environment.line_statement_prefix), 'linestatement',
-                      r'^\s*' + e(environment.line_statement_prefix)))
-    if environment.line_comment_prefix is not None:
-        rules.append((len(environment.line_comment_prefix), 'linecomment',
-                      r'(?:^|(?<=\S))[^\S\r\n]*' +
-                      e(environment.line_comment_prefix)))
-
-    return [x[1:] for x in sorted(rules, reverse=True)]
-
-
-class Failure(object):
-    """Class that raises a `TemplateSyntaxError` if called.
-    Used by the `Lexer` to specify known errors.
-    """
-
-    def __init__(self, message, cls=TemplateSyntaxError):
-        self.message = message
-        self.error_class = cls
-
-    def __call__(self, lineno, filename):
-        raise self.error_class(self.message, lineno, filename)
-
-
-class Token(tuple):
-    """Token class."""
-    __slots__ = ()
-    lineno, type, value = (property(itemgetter(x)) for x in range(3))
-
-    def __new__(cls, lineno, type, value):
-        return tuple.__new__(cls, (lineno, intern(str(type)), value))
-
-    def __str__(self):
-        if self.type in reverse_operators:
-            return reverse_operators[self.type]
-        elif self.type == 'name':
-            return self.value
-        return self.type
-
-    def test(self, expr):
-        """Test a token against a token expression.  This can either be a
-        token type or ``'token_type:token_value'``.  This can only test
-        against string values and types.
-        """
-        # here we do a regular string equality check as test_any is usually
-        # passed an iterable of not interned strings.
-        if self.type == expr:
-            return True
-        elif ':' in expr:
-            return expr.split(':', 1) == [self.type, self.value]
-        return False
-
-    def test_any(self, *iterable):
-        """Test against multiple token expressions."""
-        for expr in iterable:
-            if self.test(expr):
-                return True
-        return False
-
-    def __repr__(self):
-        return 'Token(%r, %r, %r)' % (
-            self.lineno,
-            self.type,
-            self.value
-        )
-
-
-class TokenStreamIterator(object):
-    """The iterator for tokenstreams.  Iterate over the stream
-    until the eof token is reached.
-    """
-
-    def __init__(self, stream):
-        self.stream = stream
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        token = self.stream.current
-        if token.type is TOKEN_EOF:
-            self.stream.close()
-            raise StopIteration()
-        next(self.stream)
-        return token
-
-
-class TokenStream(object):
-    """A token stream is an iterable that yields :class:`Token`\s.  The
-    parser however does not iterate over it but calls :meth:`next` to go
-    one token ahead.  The current active token is stored as :attr:`current`.
-    """
-
-    def __init__(self, generator, name, filename):
-        self._next = iter(generator).next
-        self._pushed = deque()
-        self.name = name
-        self.filename = filename
-        self.closed = False
-        self.current = Token(1, TOKEN_INITIAL, '')
-        next(self)
-
-    def __iter__(self):
-        return TokenStreamIterator(self)
-
-    def __nonzero__(self):
-        return bool(self._pushed) or self.current.type is not TOKEN_EOF
-
-    eos = property(lambda x: not x, doc="Are we at the end of the stream?")
-
-    def push(self, token):
-        """Push a token back to the stream."""
-        self._pushed.append(token)
-
-    def look(self):
-        """Look at the next token."""
-        old_token = next(self)
-        result = self.current
-        self.push(result)
-        self.current = old_token
-        return result
-
-    def skip(self, n=1):
-        """Got n tokens ahead."""
-        for x in xrange(n):
-            next(self)
-
-    def next_if(self, expr):
-        """Perform the token test and return the token if it matched.
-        Otherwise the return value is `None`.
-        """
-        if self.current.test(expr):
-            return next(self)
-
-    def skip_if(self, expr):
-        """Like :meth:`next_if` but only returns `True` or `False`."""
-        return self.next_if(expr) is not None
-
-    def next(self):
-        """Go one token ahead and return the old one"""
-        rv = self.current
-        if self._pushed:
-            self.current = self._pushed.popleft()
-        elif self.current.type is not TOKEN_EOF:
-            try:
-                self.current = self._next()
-            except StopIteration:
-                self.close()
-        return rv
-
-    def close(self):
-        """Close the stream."""
-        self.current = Token(self.current.lineno, TOKEN_EOF, '')
-        self._next = None
-        self.closed = True
-
-    def expect(self, expr):
-        """Expect a given token type and return it.  This accepts the same
-        argument as :meth:`jinja2.lexer.Token.test`.
-        """
-        if not self.current.test(expr):
-            expr = describe_token_expr(expr)
-            if self.current.type is TOKEN_EOF:
-                raise TemplateSyntaxError('unexpected end of template, '
-                                          'expected %r.' % expr,
-                                          self.current.lineno,
-                                          self.name, self.filename)
-            raise TemplateSyntaxError("expected token %r, got %r" %
-                                      (expr, describe_token(self.current)),
-                                      self.current.lineno,
-                                      self.name, self.filename)
-        try:
-            return self.current
-        finally:
-            next(self)
-
-
-def get_lexer(environment):
-    """Return a lexer which is probably cached."""
-    key = (environment.block_start_string,
-           environment.block_end_string,
-           environment.variable_start_string,
-           environment.variable_end_string,
-           environment.comment_start_string,
-           environment.comment_end_string,
-           environment.line_statement_prefix,
-           environment.line_comment_prefix,
-           environment.trim_blocks,
-           environment.newline_sequence)
-    lexer = _lexer_cache.get(key)
-    if lexer is None:
-        lexer = Lexer(environment)
-        _lexer_cache[key] = lexer
-    return lexer
-
-
-class Lexer(object):
-    """Class that implements a lexer for a given environment. Automatically
-    created by the environment class, usually you don't have to do that.
-
-    Note that the lexer is not automatically bound to an environment.
-    Multiple environments can share the same lexer.
-    """
-
-    def __init__(self, environment):
-        # shortcuts
-        c = lambda x: re.compile(x, re.M | re.S)
-        e = re.escape
-
-        # lexing rules for tags
-        tag_rules = [
-            (whitespace_re, TOKEN_WHITESPACE, None),
-            (float_re, TOKEN_FLOAT, None),
-            (integer_re, TOKEN_INTEGER, None),
-            (name_re, TOKEN_NAME, None),
-            (string_re, TOKEN_STRING, None),
-            (operator_re, TOKEN_OPERATOR, None)
-        ]
-
-        # assamble the root lexing rule. because "|" is ungreedy
-        # we have to sort by length so that the lexer continues working
-        # as expected when we have parsing rules like <% for block and
-        # <%= for variables. (if someone wants asp like syntax)
-        # variables are just part of the rules if variable processing
-        # is required.
-        root_tag_rules = compile_rules(environment)
-
-        # block suffix if trimming is enabled
-        block_suffix_re = environment.trim_blocks and '\\n?' or ''
-
-        self.newline_sequence = environment.newline_sequence
-
-        # global lexing rules
-        self.rules = {
-            'root': [
-                # directives
-                (c('(.*?)(?:%s)' % '|'.join(
-                    [r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
-                        e(environment.block_start_string),
-                        e(environment.block_start_string),
-                        e(environment.block_end_string),
-                        e(environment.block_end_string)
-                    )] + [
-                        r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, r)
-                        for n, r in root_tag_rules
-                    ])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
-                # data
-                (c('.+'), TOKEN_DATA, None)
-            ],
-            # comments
-            TOKEN_COMMENT_BEGIN: [
-                (c(r'(.*?)((?:\-%s\s*|%s)%s)' % (
-                    e(environment.comment_end_string),
-                    e(environment.comment_end_string),
-                    block_suffix_re
-                )), (TOKEN_COMMENT, TOKEN_COMMENT_END), '#pop'),
-                (c('(.)'), (Failure('Missing end of comment tag'),), None)
-            ],
-            # blocks
-            TOKEN_BLOCK_BEGIN: [
-                (c('(?:\-%s\s*|%s)%s' % (
-                    e(environment.block_end_string),
-                    e(environment.block_end_string),
-                    block_suffix_re
-                )), TOKEN_BLOCK_END, '#pop'),
-            ] + tag_rules,
-            # variables
-            TOKEN_VARIABLE_BEGIN: [
-                (c('\-%s\s*|%s' % (
-                    e(environment.variable_end_string),
-                    e(environment.variable_end_string)
-                )), TOKEN_VARIABLE_END, '#pop')
-            ] + tag_rules,
-            # raw block
-            TOKEN_RAW_BEGIN: [
-                (c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
-                    e(environment.block_start_string),
-                    e(environment.block_start_string),
-                    e(environment.block_end_string),
-                    e(environment.block_end_string),
-                    block_suffix_re
-                )), (TOKEN_DATA, TOKEN_RAW_END), '#pop'),
-                (c('(.)'), (Failure('Missing end of raw directive'),), None)
-            ],
-            # line statements
-            TOKEN_LINESTATEMENT_BEGIN: [
-                (c(r'\s*(\n|$)'), TOKEN_LINESTATEMENT_END, '#pop')
-            ] + tag_rules,
-            # line comments
-            TOKEN_LINECOMMENT_BEGIN: [
-                (c(r'(.*?)()(?=\n|$)'), (TOKEN_LINECOMMENT,
-                 TOKEN_LINECOMMENT_END), '#pop')
-            ]
-        }
-
-    def _normalize_newlines(self, value):
-        """Called for strings and template data to normlize it to unicode."""
-        return newline_re.sub(self.newline_sequence, value)
-
-    def tokenize(self, source, name=None, filename=None, state=None):
-        """Calls tokeniter + tokenize and wraps it in a token stream.
-        """
-        stream = self.tokeniter(source, name, filename, state)
-        return TokenStream(self.wrap(stream, name, filename), name, filename)
-
-    def wrap(self, stream, name=None, filename=None):
-        """This is called with the stream as returned by `tokenize` and wraps
-        every token in a :class:`Token` and converts the value.
-        """
-        for lineno, token, value in stream:
-            if token in ignored_tokens:
-                continue
-            elif token == 'linestatement_begin':
-                token = 'block_begin'
-            elif token == 'linestatement_end':
-                token = 'block_end'
-            # we are not interested in those tokens in the parser
-            elif token in ('raw_begin', 'raw_end'):
-                continue
-            elif token == 'data':
-                value = self._normalize_newlines(value)
-            elif token == 'keyword':
-                token = value
-            elif token == 'name':
-                value = str(value)
-            elif token == 'string':
-                # try to unescape string
-                try:
-                    value = self._normalize_newlines(value[1:-1]) \
-                        .encode('ascii', 'backslashreplace') \
-                        .decode('unicode-escape')
-                except Exception, e:
-                    msg = str(e).split(':')[-1].strip()
-                    raise TemplateSyntaxError(msg, lineno, name, filename)
-                # if we can express it as bytestring (ascii only)
-                # we do that for support of semi broken APIs
-                # as datetime.datetime.strftime.  On python 3 this
-                # call becomes a noop thanks to 2to3
-                try:
-                    value = str(value)
-                except UnicodeError:
-                    pass
-            elif token == 'integer':
-                value = int(value)
-            elif token == 'float':
-                value = float(value)
-            elif token == 'operator':
-                token = operators[value]
-            yield Token(lineno, token, value)
-
-    def tokeniter(self, source, name, filename=None, state=None):
-        """This method tokenizes the text and returns the tokens in a
-        generator.  Use this method if you just want to tokenize a template.
-        """
-        source = '\n'.join(unicode(source).splitlines())
-        pos = 0
-        lineno = 1
-        stack = ['root']
-        if state is not None and state != 'root':
-            assert state in ('variable', 'block'), 'invalid state'
-            stack.append(state + '_begin')
-        else:
-            state = 'root'
-        statetokens = self.rules[stack[-1]]
-        source_length = len(source)
-
-        balancing_stack = []
-
-        while 1:
-            # tokenizer loop
-            for regex, tokens, new_state in statetokens:
-                m = regex.match(source, pos)
-                # if no match we try again with the next rule
-                if m is None:
-                    continue
-
-                # we only match blocks and variables if brances / parentheses
-                # are balanced. continue parsing with the lower rule which
-                # is the operator rule. do this only if the end tags look
-                # like operators
-                if balancing_stack and \
-                   tokens in ('variable_end', 'block_end',
-                              'linestatement_end'):
-                    continue
-
-                # tuples support more options
-                if isinstance(tokens, tuple):
-                    for idx, token in enumerate(tokens):
-                        # failure group
-                        if token.__class__ is Failure:
-                            raise token(lineno, filename)
-                        # bygroup is a bit more complex, in that case we
-                        # yield for the current token the first named
-                        # group that matched
-                        elif token == '#bygroup':
-                            for key, value in m.groupdict().iteritems():
-                                if value is not None:
-                                    yield lineno, key, value
-                                    lineno += value.count('\n')
-                                    break
-                            else:
-                                raise RuntimeError('%r wanted to resolve '
-                                                   'the token dynamically'
-                                                   ' but no group matched'
-                                                   % regex)
-                        # normal group
-                        else:
-                            data = m.group(idx + 1)
-                            if data or token not in ignore_if_empty:
-                                yield lineno, token, data
-                            lineno += data.count('\n')
-
-                # strings as token just are yielded as it.
-                else:
-                    data = m.group()
-                    # update brace/parentheses balance
-                    if tokens == 'operator':
-                        if data == '{':
-                            balancing_stack.append('}')
-                        elif data == '(':
-                            balancing_stack.append(')')
-                        elif data == '[':
-                            balancing_stack.append(']')
-                        elif data in ('}', ')', ']'):
-                            if not balancing_stack:
-                                raise TemplateSyntaxError('unexpected \'%s\'' %
-                                                          data, lineno, name,
-                                                          filename)
-                            expected_op = balancing_stack.pop()
-                            if expected_op != data:
-                                raise TemplateSyntaxError('unexpected \'%s\', '
-                                                          'expected \'%s\'' %
-                                                          (data, expected_op),
-                                                          lineno, name,
-                                                          filename)
-                    # yield items
-                    if data or tokens not in ignore_if_empty:
-                        yield lineno, tokens, data
-                    lineno += data.count('\n')
-
-                # fetch new position into new variable so that we can check
-                # if there is a internal parsing error which would result
-                # in an infinite loop
-                pos2 = m.end()
-
-                # handle state changes
-                if new_state is not None:
-                    # remove the uppermost state
-                    if new_state == '#pop':
-                        stack.pop()
-                    # resolve the new state by group checking
-                    elif new_state == '#bygroup':
-                        for key, value in m.groupdict().iteritems():
-                            if value is not None:
-                                stack.append(key)
-                                break
-                        else:
-                            raise RuntimeError('%r wanted to resolve the '
-                                               'new state dynamically but'
-                                               ' no group matched' %
-                                               regex)
-                    # direct state name given
-                    else:
-                        stack.append(new_state)
-                    statetokens = self.rules[stack[-1]]
-                # we are still at the same position and no stack change.
-                # this means a loop without break condition, avoid that and
-                # raise error
-                elif pos2 == pos:
-                    raise RuntimeError('%r yielded empty string without '
-                                       'stack change' % regex)
-                # publish new function and start again
-                pos = pos2
-                break
-            # if loop terminated without break we havn't found a single match
-            # either we are at the end of the file or we have a problem
-            else:
-                # end of text
-                if pos >= source_length:
-                    return
-                # something went wrong
-                raise TemplateSyntaxError('unexpected char %r at %d' %
-                                          (source[pos], pos), lineno,
-                                          name, filename)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/loaders.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/loaders.py b/ambari-common/src/main/python/jinja2/jinja2/loaders.py
deleted file mode 100644
index bd435e8..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/loaders.py
+++ /dev/null
@@ -1,449 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.loaders
-    ~~~~~~~~~~~~~~
-
-    Jinja loader classes.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import weakref
-from types import ModuleType
-from os import path
-try:
-    from hashlib import sha1
-except ImportError:
-    from sha import new as sha1
-from jinja2.exceptions import TemplateNotFound
-from jinja2.utils import LRUCache, open_if_exists, internalcode
-
-
-def split_template_path(template):
-    """Split a path into segments and perform a sanity check.  If it detects
-    '..' in the path it will raise a `TemplateNotFound` error.
-    """
-    pieces = []
-    for piece in template.split('/'):
-        if path.sep in piece \
-           or (path.altsep and path.altsep in piece) or \
-           piece == path.pardir:
-            raise TemplateNotFound(template)
-        elif piece and piece != '.':
-            pieces.append(piece)
-    return pieces
-
-
-class BaseLoader(object):
-    """Baseclass for all loaders.  Subclass this and override `get_source` to
-    implement a custom loading mechanism.  The environment provides a
-    `get_template` method that calls the loader's `load` method to get the
-    :class:`Template` object.
-
-    A very basic example for a loader that looks up templates on the file
-    system could look like this::
-
-        from jinja2 import BaseLoader, TemplateNotFound
-        from os.path import join, exists, getmtime
-
-        class MyLoader(BaseLoader):
-
-            def __init__(self, path):
-                self.path = path
-
-            def get_source(self, environment, template):
-                path = join(self.path, template)
-                if not exists(path):
-                    raise TemplateNotFound(template)
-                mtime = getmtime(path)
-                with file(path) as f:
-                    source = f.read().decode('utf-8')
-                return source, path, lambda: mtime == getmtime(path)
-    """
-
-    #: if set to `False` it indicates that the loader cannot provide access
-    #: to the source of templates.
-    #:
-    #: .. versionadded:: 2.4
-    has_source_access = True
-
-    def get_source(self, environment, template):
-        """Get the template source, filename and reload helper for a template.
-        It's passed the environment and template name and has to return a
-        tuple in the form ``(source, filename, uptodate)`` or raise a
-        `TemplateNotFound` error if it can't locate the template.
-
-        The source part of the returned tuple must be the source of the
-        template as unicode string or a ASCII bytestring.  The filename should
-        be the name of the file on the filesystem if it was loaded from there,
-        otherwise `None`.  The filename is used by python for the tracebacks
-        if no loader extension is used.
-
-        The last item in the tuple is the `uptodate` function.  If auto
-        reloading is enabled it's always called to check if the template
-        changed.  No arguments are passed so the function must store the
-        old state somewhere (for example in a closure).  If it returns `False`
-        the template will be reloaded.
-        """
-        if not self.has_source_access:
-            raise RuntimeError('%s cannot provide access to the source' %
-                               self.__class__.__name__)
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        """Iterates over all templates.  If the loader does not support that
-        it should raise a :exc:`TypeError` which is the default behavior.
-        """
-        raise TypeError('this loader cannot iterate over all templates')
-
-    @internalcode
-    def load(self, environment, name, globals=None):
-        """Loads a template.  This method looks up the template in the cache
-        or loads one by calling :meth:`get_source`.  Subclasses should not
-        override this method as loaders working on collections of other
-        loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)
-        will not call this method but `get_source` directly.
-        """
-        code = None
-        if globals is None:
-            globals = {}
-
-        # first we try to get the source for this template together
-        # with the filename and the uptodate function.
-        source, filename, uptodate = self.get_source(environment, name)
-
-        # try to load the code from the bytecode cache if there is a
-        # bytecode cache configured.
-        bcc = environment.bytecode_cache
-        if bcc is not None:
-            bucket = bcc.get_bucket(environment, name, filename, source)
-            code = bucket.code
-
-        # if we don't have code so far (not cached, no longer up to
-        # date) etc. we compile the template
-        if code is None:
-            code = environment.compile(source, name, filename)
-
-        # if the bytecode cache is available and the bucket doesn't
-        # have a code so far, we give the bucket the new code and put
-        # it back to the bytecode cache.
-        if bcc is not None and bucket.code is None:
-            bucket.code = code
-            bcc.set_bucket(bucket)
-
-        return environment.template_class.from_code(environment, code,
-                                                    globals, uptodate)
-
-
-class FileSystemLoader(BaseLoader):
-    """Loads templates from the file system.  This loader can find templates
-    in folders on the file system and is the preferred way to load them.
-
-    The loader takes the path to the templates as string, or if multiple
-    locations are wanted a list of them which is then looked up in the
-    given order:
-
-    >>> loader = FileSystemLoader('/path/to/templates')
-    >>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
-
-    Per default the template encoding is ``'utf-8'`` which can be changed
-    by setting the `encoding` parameter to something else.
-    """
-
-    def __init__(self, searchpath, encoding='utf-8'):
-        if isinstance(searchpath, basestring):
-            searchpath = [searchpath]
-        self.searchpath = list(searchpath)
-        self.encoding = encoding
-
-    def get_source(self, environment, template):
-        pieces = split_template_path(template)
-        for searchpath in self.searchpath:
-            filename = path.join(searchpath, *pieces)
-            f = open_if_exists(filename)
-            if f is None:
-                continue
-            try:
-                contents = f.read().decode(self.encoding)
-            finally:
-                f.close()
-
-            mtime = path.getmtime(filename)
-            def uptodate():
-                try:
-                    return path.getmtime(filename) == mtime
-                except OSError:
-                    return False
-            return contents, filename, uptodate
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        found = set()
-        for searchpath in self.searchpath:
-            for dirpath, dirnames, filenames in os.walk(searchpath):
-                for filename in filenames:
-                    template = os.path.join(dirpath, filename) \
-                        [len(searchpath):].strip(os.path.sep) \
-                                          .replace(os.path.sep, '/')
-                    if template[:2] == './':
-                        template = template[2:]
-                    if template not in found:
-                        found.add(template)
-        return sorted(found)
-
-
-class PackageLoader(BaseLoader):
-    """Load templates from python eggs or packages.  It is constructed with
-    the name of the python package and the path to the templates in that
-    package::
-
-        loader = PackageLoader('mypackage', 'views')
-
-    If the package path is not given, ``'templates'`` is assumed.
-
-    Per default the template encoding is ``'utf-8'`` which can be changed
-    by setting the `encoding` parameter to something else.  Due to the nature
-    of eggs it's only possible to reload templates if the package was loaded
-    from the file system and not a zip file.
-    """
-
-    def __init__(self, package_name, package_path='templates',
-                 encoding='utf-8'):
-        from pkg_resources import DefaultProvider, ResourceManager, \
-                                  get_provider
-        provider = get_provider(package_name)
-        self.encoding = encoding
-        self.manager = ResourceManager()
-        self.filesystem_bound = isinstance(provider, DefaultProvider)
-        self.provider = provider
-        self.package_path = package_path
-
-    def get_source(self, environment, template):
-        pieces = split_template_path(template)
-        p = '/'.join((self.package_path,) + tuple(pieces))
-        if not self.provider.has_resource(p):
-            raise TemplateNotFound(template)
-
-        filename = uptodate = None
-        if self.filesystem_bound:
-            filename = self.provider.get_resource_filename(self.manager, p)
-            mtime = path.getmtime(filename)
-            def uptodate():
-                try:
-                    return path.getmtime(filename) == mtime
-                except OSError:
-                    return False
-
-        source = self.provider.get_resource_string(self.manager, p)
-        return source.decode(self.encoding), filename, uptodate
-
-    def list_templates(self):
-        path = self.package_path
-        if path[:2] == './':
-            path = path[2:]
-        elif path == '.':
-            path = ''
-        offset = len(path)
-        results = []
-        def _walk(path):
-            for filename in self.provider.resource_listdir(path):
-                fullname = path + '/' + filename
-                if self.provider.resource_isdir(fullname):
-                    for item in _walk(fullname):
-                        results.append(item)
-                else:
-                    results.append(fullname[offset:].lstrip('/'))
-        _walk(path)
-        results.sort()
-        return results
-
-
-class DictLoader(BaseLoader):
-    """Loads a template from a python dict.  It's passed a dict of unicode
-    strings bound to template names.  This loader is useful for unittesting:
-
-    >>> loader = DictLoader({'index.html': 'source here'})
-
-    Because auto reloading is rarely useful this is disabled per default.
-    """
-
-    def __init__(self, mapping):
-        self.mapping = mapping
-
-    def get_source(self, environment, template):
-        if template in self.mapping:
-            source = self.mapping[template]
-            return source, None, lambda: source != self.mapping.get(template)
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        return sorted(self.mapping)
-
-
-class FunctionLoader(BaseLoader):
-    """A loader that is passed a function which does the loading.  The
-    function becomes the name of the template passed and has to return either
-    an unicode string with the template source, a tuple in the form ``(source,
-    filename, uptodatefunc)`` or `None` if the template does not exist.
-
-    >>> def load_template(name):
-    ...     if name == 'index.html':
-    ...         return '...'
-    ...
-    >>> loader = FunctionLoader(load_template)
-
-    The `uptodatefunc` is a function that is called if autoreload is enabled
-    and has to return `True` if the template is still up to date.  For more
-    details have a look at :meth:`BaseLoader.get_source` which has the same
-    return value.
-    """
-
-    def __init__(self, load_func):
-        self.load_func = load_func
-
-    def get_source(self, environment, template):
-        rv = self.load_func(template)
-        if rv is None:
-            raise TemplateNotFound(template)
-        elif isinstance(rv, basestring):
-            return rv, None, None
-        return rv
-
-
-class PrefixLoader(BaseLoader):
-    """A loader that is passed a dict of loaders where each loader is bound
-    to a prefix.  The prefix is delimited from the template by a slash per
-    default, which can be changed by setting the `delimiter` argument to
-    something else::
-
-        loader = PrefixLoader({
-            'app1':     PackageLoader('mypackage.app1'),
-            'app2':     PackageLoader('mypackage.app2')
-        })
-
-    By loading ``'app1/index.html'`` the file from the app1 package is loaded,
-    by loading ``'app2/index.html'`` the file from the second.
-    """
-
-    def __init__(self, mapping, delimiter='/'):
-        self.mapping = mapping
-        self.delimiter = delimiter
-
-    def get_source(self, environment, template):
-        try:
-            prefix, name = template.split(self.delimiter, 1)
-            loader = self.mapping[prefix]
-        except (ValueError, KeyError):
-            raise TemplateNotFound(template)
-        try:
-            return loader.get_source(environment, name)
-        except TemplateNotFound:
-            # re-raise the exception with the correct fileame here.
-            # (the one that includes the prefix)
-            raise TemplateNotFound(template)
-
-    def list_templates(self):
-        result = []
-        for prefix, loader in self.mapping.iteritems():
-            for template in loader.list_templates():
-                result.append(prefix + self.delimiter + template)
-        return result
-
-
-class ChoiceLoader(BaseLoader):
-    """This loader works like the `PrefixLoader` just that no prefix is
-    specified.  If a template could not be found by one loader the next one
-    is tried.
-
-    >>> loader = ChoiceLoader([
-    ...     FileSystemLoader('/path/to/user/templates'),
-    ...     FileSystemLoader('/path/to/system/templates')
-    ... ])
-
-    This is useful if you want to allow users to override builtin templates
-    from a different location.
-    """
-
-    def __init__(self, loaders):
-        self.loaders = loaders
-
-    def get_source(self, environment, template):
-        for loader in self.loaders:
-            try:
-                return loader.get_source(environment, template)
-            except TemplateNotFound:
-                pass
-        raise TemplateNotFound(template)
-
-    def list_templates(self):
-        found = set()
-        for loader in self.loaders:
-            found.update(loader.list_templates())
-        return sorted(found)
-
-
-class _TemplateModule(ModuleType):
-    """Like a normal module but with support for weak references"""
-
-
-class ModuleLoader(BaseLoader):
-    """This loader loads templates from precompiled templates.
-
-    Example usage:
-
-    >>> loader = ChoiceLoader([
-    ...     ModuleLoader('/path/to/compiled/templates'),
-    ...     FileSystemLoader('/path/to/templates')
-    ... ])
-    """
-
-    has_source_access = False
-
-    def __init__(self, path):
-        package_name = '_jinja2_module_templates_%x' % id(self)
-
-        # create a fake module that looks for the templates in the
-        # path given.
-        mod = _TemplateModule(package_name)
-        if isinstance(path, basestring):
-            path = [path]
-        else:
-            path = list(path)
-        mod.__path__ = path
-
-        sys.modules[package_name] = weakref.proxy(mod,
-            lambda x: sys.modules.pop(package_name, None))
-
-        # the only strong reference, the sys.modules entry is weak
-        # so that the garbage collector can remove it once the
-        # loader that created it goes out of business.
-        self.module = mod
-        self.package_name = package_name
-
-    @staticmethod
-    def get_template_key(name):
-        return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest()
-
-    @staticmethod
-    def get_module_filename(name):
-        return ModuleLoader.get_template_key(name) + '.py'
-
-    @internalcode
-    def load(self, environment, name, globals=None):
-        key = self.get_template_key(name)
-        module = '%s.%s' % (self.package_name, key)
-        mod = getattr(self.module, module, None)
-        if mod is None:
-            try:
-                mod = __import__(module, None, None, ['root'])
-            except ImportError:
-                raise TemplateNotFound(name)
-
-            # remove the entry from sys.modules, we only want the attribute
-            # on the module object we have stored on the loader.
-            sys.modules.pop(module, None)
-
-        return environment.template_class.from_module_dict(
-            environment, mod.__dict__, globals)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/meta.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/meta.py b/ambari-common/src/main/python/jinja2/jinja2/meta.py
deleted file mode 100644
index 3a779a5..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/meta.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.meta
-    ~~~~~~~~~~~
-
-    This module implements various functions that exposes information about
-    templates that might be interesting for various kinds of applications.
-
-    :copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-from jinja2 import nodes
-from jinja2.compiler import CodeGenerator
-
-
-class TrackingCodeGenerator(CodeGenerator):
-    """We abuse the code generator for introspection."""
-
-    def __init__(self, environment):
-        CodeGenerator.__init__(self, environment, '<introspection>',
-                               '<introspection>')
-        self.undeclared_identifiers = set()
-
-    def write(self, x):
-        """Don't write."""
-
-    def pull_locals(self, frame):
-        """Remember all undeclared identifiers."""
-        self.undeclared_identifiers.update(frame.identifiers.undeclared)
-
-
-def find_undeclared_variables(ast):
-    """Returns a set of all variables in the AST that will be looked up from
-    the context at runtime.  Because at compile time it's not known which
-    variables will be used depending on the path the execution takes at
-    runtime, all variables are returned.
-
-    >>> from jinja2 import Environment, meta
-    >>> env = Environment()
-    >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
-    >>> meta.find_undeclared_variables(ast)
-    set(['bar'])
-
-    .. admonition:: Implementation
-
-       Internally the code generator is used for finding undeclared variables.
-       This is good to know because the code generator might raise a
-       :exc:`TemplateAssertionError` during compilation and as a matter of
-       fact this function can currently raise that exception as well.
-    """
-    codegen = TrackingCodeGenerator(ast.environment)
-    codegen.visit(ast)
-    return codegen.undeclared_identifiers
-
-
-def find_referenced_templates(ast):
-    """Finds all the referenced templates from the AST.  This will return an
-    iterator over all the hardcoded template extensions, inclusions and
-    imports.  If dynamic inheritance or inclusion is used, `None` will be
-    yielded.
-
-    >>> from jinja2 import Environment, meta
-    >>> env = Environment()
-    >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
-    >>> list(meta.find_referenced_templates(ast))
-    ['layout.html', None]
-
-    This function is useful for dependency tracking.  For example if you want
-    to rebuild parts of the website after a layout template has changed.
-    """
-    for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import,
-                              nodes.Include)):
-        if not isinstance(node.template, nodes.Const):
-            # a tuple with some non consts in there
-            if isinstance(node.template, (nodes.Tuple, nodes.List)):
-                for template_name in node.template.items:
-                    # something const, only yield the strings and ignore
-                    # non-string consts that really just make no sense
-                    if isinstance(template_name, nodes.Const):
-                        if isinstance(template_name.value, basestring):
-                            yield template_name.value
-                    # something dynamic in there
-                    else:
-                        yield None
-            # something dynamic we don't know about here
-            else:
-                yield None
-            continue
-        # constant is a basestring, direct template name
-        if isinstance(node.template.value, basestring):
-            yield node.template.value
-        # a tuple or list (latter *should* not happen) made of consts,
-        # yield the consts that are strings.  We could warn here for
-        # non string values
-        elif isinstance(node, nodes.Include) and \
-             isinstance(node.template.value, (tuple, list)):
-            for template_name in node.template.value:
-                if isinstance(template_name, basestring):
-                    yield template_name
-        # something else we don't care about, we could warn here
-        else:
-            yield None


[58/59] [abbrv] git commit: AMBARI-7149. Unable to edit password and email fields on Step 7 of installer - Nagios and Hive. (jaimin)

Posted by nc...@apache.org.
AMBARI-7149. Unable to edit password and email fields on Step 7 of installer - Nagios and Hive. (jaimin)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ad983dee
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ad983dee
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ad983dee

Branch: refs/heads/branch-alerts-dev
Commit: ad983dee1c4b5a6d054fd614084a39e9d9a1a416
Parents: 1946654
Author: Jaimin Jetly <ja...@hortonworks.com>
Authored: Thu Sep 4 14:21:37 2014 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Thu Sep 4 14:21:37 2014 -0700

----------------------------------------------------------------------
 ambari-web/app/views/common/configs/services_config.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ad983dee/ambari-web/app/views/common/configs/services_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/services_config.js b/ambari-web/app/views/common/configs/services_config.js
index aa189b3..f54a554 100644
--- a/ambari-web/app/views/common/configs/services_config.js
+++ b/ambari-web/app/views/common/configs/services_config.js
@@ -397,7 +397,7 @@ App.ServiceConfigsByCategoryView = Ember.View.extend(App.UserPref, {
     var categoryBlock = $('.' + this.get('category.name').split(' ').join('.') + '>.accordion-body');
     filteredResult.length && !this.get('category.isCollapsed') ? categoryBlock.show() : categoryBlock.hide();
     return filteredResult;
-  }.property('categoryConfigs', 'parentView.filter', 'parentView.columns.@each.selected', 'categoryConfigs.@each.isValid').cacheable(),
+  }.property('categoryConfigs', 'parentView.filter', 'parentView.columns.@each.selected').cacheable(),
 
   /**
    * sort configs in current category by index


[45/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py
new file mode 100644
index 0000000..020c82a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/sandbox.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.sandbox
+    ~~~~~~~~~~~~~~
+
+    Adds a sandbox layer to Jinja as it was the default behavior in the old
+    Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
+    default behavior is easier to use.
+
+    The behavior can be changed by subclassing the environment.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+import operator
+from ambari_jinja2.runtime import Undefined
+from ambari_jinja2.environment import Environment
+from ambari_jinja2.exceptions import SecurityError
+from ambari_jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
+     FrameType, GeneratorType
+
+
+#: maximum number of items a range may produce
+MAX_RANGE = 100000
+
+#: attributes of function objects that are considered unsafe.
+UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
+                                  'func_defaults', 'func_globals'])
+
+#: unsafe method attributes.  function attributes are unsafe for methods too
+UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
+
+
+import warnings
+
+# make sure we don't warn in python 2.6 about stuff we don't care about
+warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
+                        module='ambari_jinja2.sandbox')
+
+from collections import deque
+
+_mutable_set_types = (set,)
+_mutable_mapping_types = (dict,)
+_mutable_sequence_types = (list,)
+
+
+# on python 2.x we can register the user collection types
+try:
+    from UserDict import UserDict, DictMixin
+    from UserList import UserList
+    _mutable_mapping_types += (UserDict, DictMixin)
+    _mutable_set_types += (UserList,)
+except ImportError:
+    pass
+
+# if sets is still available, register the mutable set from there as well
+try:
+    from sets import Set
+    _mutable_set_types += (Set,)
+except ImportError:
+    pass
+
+#: register Python 2.6 abstract base classes
+try:
+    from collections import MutableSet, MutableMapping, MutableSequence
+    _mutable_set_types += (MutableSet,)
+    _mutable_mapping_types += (MutableMapping,)
+    _mutable_sequence_types += (MutableSequence,)
+except ImportError:
+    pass
+
+_mutable_spec = (
+    (_mutable_set_types, frozenset([
+        'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
+        'symmetric_difference_update', 'update'
+    ])),
+    (_mutable_mapping_types, frozenset([
+        'clear', 'pop', 'popitem', 'setdefault', 'update'
+    ])),
+    (_mutable_sequence_types, frozenset([
+        'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
+    ])),
+    (deque, frozenset([
+        'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
+        'popleft', 'remove', 'rotate'
+    ]))
+)
+
+
+def safe_range(*args):
+    """A range that can't generate ranges with a length of more than
+    MAX_RANGE items.
+    """
+    rng = xrange(*args)
+    if len(rng) > MAX_RANGE:
+        raise OverflowError('range too big, maximum size for range is %d' %
+                            MAX_RANGE)
+    return rng
+
+
+def unsafe(f):
+    """
+    Mark a function or method as unsafe::
+
+        @unsafe
+        def delete(self):
+            pass
+    """
+    f.unsafe_callable = True
+    return f
+
+
+def is_internal_attribute(obj, attr):
+    """Test if the attribute given is an internal python attribute.  For
+    example this function returns `True` for the `func_code` attribute of
+    python objects.  This is useful if the environment method
+    :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
+
+    >>> from ambari_jinja2.sandbox import is_internal_attribute
+    >>> is_internal_attribute(lambda: None, "func_code")
+    True
+    >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
+    True
+    >>> is_internal_attribute(str, "upper")
+    False
+    """
+    if isinstance(obj, FunctionType):
+        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
+            return True
+    elif isinstance(obj, MethodType):
+        if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
+           attr in UNSAFE_METHOD_ATTRIBUTES:
+            return True
+    elif isinstance(obj, type):
+        if attr == 'mro':
+            return True
+    elif isinstance(obj, (CodeType, TracebackType, FrameType)):
+        return True
+    elif isinstance(obj, GeneratorType):
+        if attr == 'gi_frame':
+            return True
+    return attr.startswith('__')
+
+
+def modifies_known_mutable(obj, attr):
+    """This function checks if an attribute on a builtin mutable object
+    (list, dict, set or deque) would modify it if called.  It also supports
+    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
+    with Python 2.6 onwards the abstract base classes `MutableSet`,
+    `MutableMapping`, and `MutableSequence`.
+
+    >>> modifies_known_mutable({}, "clear")
+    True
+    >>> modifies_known_mutable({}, "keys")
+    False
+    >>> modifies_known_mutable([], "append")
+    True
+    >>> modifies_known_mutable([], "index")
+    False
+
+    If called with an unsupported object (such as unicode) `False` is
+    returned.
+
+    >>> modifies_known_mutable("foo", "upper")
+    False
+    """
+    for typespec, unsafe in _mutable_spec:
+        if isinstance(obj, typespec):
+            return attr in unsafe
+    return False
+
+
+class SandboxedEnvironment(Environment):
+    """The sandboxed environment.  It works like the regular environment but
+    tells the compiler to generate sandboxed code.  Additionally subclasses of
+    this environment may override the methods that tell the runtime what
+    attributes or functions are safe to access.
+
+    If the template tries to access insecure code a :exc:`SecurityError` is
+    raised.  However also other exceptions may occour during the rendering so
+    the caller has to ensure that all exceptions are catched.
+    """
+    sandboxed = True
+
+    def __init__(self, *args, **kwargs):
+        Environment.__init__(self, *args, **kwargs)
+        self.globals['range'] = safe_range
+
+    def is_safe_attribute(self, obj, attr, value):
+        """The sandboxed environment will call this method to check if the
+        attribute of an object is safe to access.  Per default all attributes
+        starting with an underscore are considered private as well as the
+        special attributes of internal python objects as returned by the
+        :func:`is_internal_attribute` function.
+        """
+        return not (attr.startswith('_') or is_internal_attribute(obj, attr))
+
+    def is_safe_callable(self, obj):
+        """Check if an object is safely callable.  Per default a function is
+        considered safe unless the `unsafe_callable` attribute exists and is
+        True.  Override this method to alter the behavior, but this won't
+        affect the `unsafe` decorator from this module.
+        """
+        return not (getattr(obj, 'unsafe_callable', False) or \
+                    getattr(obj, 'alters_data', False))
+
+    def getitem(self, obj, argument):
+        """Subscribe an object from sandboxed code."""
+        try:
+            return obj[argument]
+        except (TypeError, LookupError):
+            if isinstance(argument, basestring):
+                try:
+                    attr = str(argument)
+                except:
+                    pass
+                else:
+                    try:
+                        value = getattr(obj, attr)
+                    except AttributeError:
+                        pass
+                    else:
+                        if self.is_safe_attribute(obj, argument, value):
+                            return value
+                        return self.unsafe_undefined(obj, argument)
+        return self.undefined(obj=obj, name=argument)
+
+    def getattr(self, obj, attribute):
+        """Subscribe an object from sandboxed code and prefer the
+        attribute.  The attribute passed *must* be a bytestring.
+        """
+        try:
+            value = getattr(obj, attribute)
+        except AttributeError:
+            try:
+                return obj[attribute]
+            except (TypeError, LookupError):
+                pass
+        else:
+            if self.is_safe_attribute(obj, attribute, value):
+                return value
+            return self.unsafe_undefined(obj, attribute)
+        return self.undefined(obj=obj, name=attribute)
+
+    def unsafe_undefined(self, obj, attribute):
+        """Return an undefined object for unsafe attributes."""
+        return self.undefined('access to attribute %r of %r '
+                              'object is unsafe.' % (
+            attribute,
+            obj.__class__.__name__
+        ), name=attribute, obj=obj, exc=SecurityError)
+
+    def call(__self, __context, __obj, *args, **kwargs):
+        """Call an object from sandboxed code."""
+        # the double prefixes are to avoid double keyword argument
+        # errors when proxying the call.
+        if not __self.is_safe_callable(__obj):
+            raise SecurityError('%r is not safely callable' % (__obj,))
+        return __context.call(__obj, *args, **kwargs)
+
+
+class ImmutableSandboxedEnvironment(SandboxedEnvironment):
+    """Works exactly like the regular `SandboxedEnvironment` but does not
+    permit modifications on the builtin mutable objects `list`, `set`, and
+    `dict` by using the :func:`modifies_known_mutable` function.
+    """
+
+    def is_safe_attribute(self, obj, attr, value):
+        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
+            return False
+        return not modifies_known_mutable(obj, attr)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py
new file mode 100644
index 0000000..4cb2bbf
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/tests.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.tests
+    ~~~~~~~~~~~~
+
+    Jinja test functions. Used with the "is" operator.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+from ambari_jinja2.runtime import Undefined
+
+# nose, nothing here to test
+__test__ = False
+
+
+number_re = re.compile(r'^-?\d+(\.\d+)?$')
+regex_type = type(number_re)
+
+
+try:
+    test_callable = callable
+except NameError:
+    def test_callable(x):
+        return hasattr(x, '__call__')
+
+
+def test_odd(value):
+    """Return true if the variable is odd."""
+    return value % 2 == 1
+
+
+def test_even(value):
+    """Return true if the variable is even."""
+    return value % 2 == 0
+
+
+def test_divisibleby(value, num):
+    """Check if a variable is divisible by a number."""
+    return value % num == 0
+
+
+def test_defined(value):
+    """Return true if the variable is defined:
+
+    .. sourcecode:: jinja
+
+        {% if variable is defined %}
+            value of variable: {{ variable }}
+        {% else %}
+            variable is not defined
+        {% endif %}
+
+    See the :func:`default` filter for a simple way to set undefined
+    variables.
+    """
+    return not isinstance(value, Undefined)
+
+
+def test_undefined(value):
+    """Like :func:`defined` but the other way round."""
+    return isinstance(value, Undefined)
+
+
+def test_none(value):
+    """Return true if the variable is none."""
+    return value is None
+
+
+def test_lower(value):
+    """Return true if the variable is lowercased."""
+    return unicode(value).islower()
+
+
+def test_upper(value):
+    """Return true if the variable is uppercased."""
+    return unicode(value).isupper()
+
+
+def test_string(value):
+    """Return true if the object is a string."""
+    return isinstance(value, basestring)
+
+
+def test_number(value):
+    """Return true if the variable is a number."""
+    return isinstance(value, (int, long, float, complex))
+
+
+def test_sequence(value):
+    """Return true if the variable is a sequence. Sequences are variables
+    that are iterable.
+    """
+    try:
+        len(value)
+        value.__getitem__
+    except:
+        return False
+    return True
+
+
+def test_sameas(value, other):
+    """Check if an object points to the same memory address than another
+    object:
+
+    .. sourcecode:: jinja
+
+        {% if foo.attribute is sameas false %}
+            the foo attribute really is the `False` singleton
+        {% endif %}
+    """
+    return value is other
+
+
+def test_iterable(value):
+    """Check if it's possible to iterate over an object."""
+    try:
+        iter(value)
+    except TypeError:
+        return False
+    return True
+
+
+def test_escaped(value):
+    """Check if the value is escaped."""
+    return hasattr(value, '__html__')
+
+
+TESTS = {
+    'odd':              test_odd,
+    'even':             test_even,
+    'divisibleby':      test_divisibleby,
+    'defined':          test_defined,
+    'undefined':        test_undefined,
+    'none':             test_none,
+    'lower':            test_lower,
+    'upper':            test_upper,
+    'string':           test_string,
+    'number':           test_number,
+    'sequence':         test_sequence,
+    'iterable':         test_iterable,
+    'callable':         test_callable,
+    'sameas':           test_sameas,
+    'escaped':          test_escaped
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py
new file mode 100644
index 0000000..cd11117
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/__init__.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite
+    ~~~~~~~~~~~~~~~~
+
+    All the unittests of Jinja2.  These tests can be executed by
+    either running run-tests.py using multiple Python versions at
+    the same time.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import re
+import sys
+import unittest
+from traceback import format_exception
+from ambari_jinja2 import loaders
+
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+dict_loader = loaders.DictLoader({
+    'justdict.html':        'FOO'
+})
+package_loader = loaders.PackageLoader('ambari_jinja2.testsuite.res', 'templates')
+filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
+function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
+choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
+prefix_loader = loaders.PrefixLoader({
+    'a':        filesystem_loader,
+    'b':        dict_loader
+})
+
+
+class JinjaTestCase(unittest.TestCase):
+
+    ### use only these methods for testing.  If you need standard
+    ### unittest method, wrap them!
+
+    def setup(self):
+        pass
+
+    def teardown(self):
+        pass
+
+    def setUp(self):
+        self.setup()
+
+    def tearDown(self):
+        self.teardown()
+
+    def assert_equal(self, a, b):
+        return self.assertEqual(a, b)
+
+    def assert_raises(self, *args, **kwargs):
+        return self.assertRaises(*args, **kwargs)
+
+    def assert_traceback_matches(self, callback, expected_tb):
+        try:
+            callback()
+        except Exception, e:
+            tb = format_exception(*sys.exc_info())
+            if re.search(expected_tb.strip(), ''.join(tb)) is None:
+                raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
+                    % (''.join(tb), expected_tb))
+        else:
+            self.fail('Expected exception')
+
+
+def suite():
+    from ambari_jinja2.testsuite import ext, filters, tests, core_tags, \
+         loader, inheritance, imports, lexnparse, security, api, \
+         regression, debug, utils, doctests
+    suite = unittest.TestSuite()
+    suite.addTest(ext.suite())
+    suite.addTest(filters.suite())
+    suite.addTest(tests.suite())
+    suite.addTest(core_tags.suite())
+    suite.addTest(loader.suite())
+    suite.addTest(inheritance.suite())
+    suite.addTest(imports.suite())
+    suite.addTest(lexnparse.suite())
+    suite.addTest(security.suite())
+    suite.addTest(api.suite())
+    suite.addTest(regression.suite())
+    suite.addTest(debug.suite())
+    suite.addTest(utils.suite())
+
+    # doctests will not run on python 3 currently.  Too many issues
+    # with that, do not test that on that platform.
+    if sys.version_info < (3, 0):
+        suite.addTest(doctests.suite())
+
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py
new file mode 100644
index 0000000..a02fb60
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/api.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.api
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Tests the public API and related stuff.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment, Undefined, DebugUndefined, \
+     StrictUndefined, UndefinedError, Template, meta, \
+     is_undefined, Template, DictLoader
+from ambari_jinja2.utils import Cycler
+
+env = Environment()
+
+
+class ExtendedAPITestCase(JinjaTestCase):
+
+    def test_item_and_attribute(self):
+        from ambari_jinja2.sandbox import SandboxedEnvironment
+
+        for env in Environment(), SandboxedEnvironment():
+            # the |list is necessary for python3
+            tmpl = env.from_string('{{ foo.items()|list }}')
+            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+            tmpl = env.from_string('{{ foo|attr("items")()|list }}')
+            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+            tmpl = env.from_string('{{ foo["items"] }}')
+            assert tmpl.render(foo={'items': 42}) == '42'
+
+    def test_finalizer(self):
+        def finalize_none_empty(value):
+            if value is None:
+                value = u''
+            return value
+        env = Environment(finalize=finalize_none_empty)
+        tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
+        assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo'
+        tmpl = env.from_string('<{{ none }}>')
+        assert tmpl.render() == '<>'
+
+    def test_cycler(self):
+        items = 1, 2, 3
+        c = Cycler(*items)
+        for item in items + items:
+            assert c.current == item
+            assert c.next() == item
+        c.next()
+        assert c.current == 2
+        c.reset()
+        assert c.current == 1
+
+    def test_expressions(self):
+        expr = env.compile_expression("foo")
+        assert expr() is None
+        assert expr(foo=42) == 42
+        expr2 = env.compile_expression("foo", undefined_to_none=False)
+        assert is_undefined(expr2())
+
+        expr = env.compile_expression("42 + foo")
+        assert expr(foo=42) == 84
+
+    def test_template_passthrough(self):
+        t = Template('Content')
+        assert env.get_template(t) is t
+        assert env.select_template([t]) is t
+        assert env.get_or_select_template([t]) is t
+        assert env.get_or_select_template(t) is t
+
+    def test_autoescape_autoselect(self):
+        def select_autoescape(name):
+            if name is None or '.' not in name:
+                return False
+            return name.endswith('.html')
+        env = Environment(autoescape=select_autoescape,
+                          loader=DictLoader({
+            'test.txt':     '{{ foo }}',
+            'test.html':    '{{ foo }}'
+        }))
+        t = env.get_template('test.txt')
+        assert t.render(foo='<foo>') == '<foo>'
+        t = env.get_template('test.html')
+        assert t.render(foo='<foo>') == '&lt;foo&gt;'
+        t = env.from_string('{{ foo }}')
+        assert t.render(foo='<foo>') == '<foo>'
+
+
+class MetaTestCase(JinjaTestCase):
+
+    def test_find_undeclared_variables(self):
+        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+        x = meta.find_undeclared_variables(ast)
+        assert x == set(['bar'])
+
+        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
+                        '{% macro meh(x) %}{{ x }}{% endmacro %}'
+                        '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
+        x = meta.find_undeclared_variables(ast)
+        assert x == set(['bar', 'seq', 'muh'])
+
+    def test_find_refererenced_templates(self):
+        ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+        i = meta.find_referenced_templates(ast)
+        assert i.next() == 'layout.html'
+        assert i.next() is None
+        assert list(i) == []
+
+        ast = env.parse('{% extends "layout.html" %}'
+                        '{% from "test.html" import a, b as c %}'
+                        '{% import "meh.html" as meh %}'
+                        '{% include "muh.html" %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
+
+    def test_find_included_templates(self):
+        ast = env.parse('{% include ["foo.html", "bar.html"] %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html']
+
+        ast = env.parse('{% include ("foo.html", "bar.html") %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html']
+
+        ast = env.parse('{% include ["foo.html", "bar.html", foo] %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html', None]
+
+        ast = env.parse('{% include ("foo.html", "bar.html", foo) %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html', None]
+
+
+class StreamingTestCase(JinjaTestCase):
+
+    def test_basic_streaming(self):
+        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+                               "}} - {{ item }}</li>{%- endfor %}</ul>")
+        stream = tmpl.stream(seq=range(4))
+        self.assert_equal(stream.next(), '<ul>')
+        self.assert_equal(stream.next(), '<li>1 - 0</li>')
+        self.assert_equal(stream.next(), '<li>2 - 1</li>')
+        self.assert_equal(stream.next(), '<li>3 - 2</li>')
+        self.assert_equal(stream.next(), '<li>4 - 3</li>')
+        self.assert_equal(stream.next(), '</ul>')
+
+    def test_buffered_streaming(self):
+        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+                               "}} - {{ item }}</li>{%- endfor %}</ul>")
+        stream = tmpl.stream(seq=range(4))
+        stream.enable_buffering(size=3)
+        self.assert_equal(stream.next(), u'<ul><li>1 - 0</li><li>2 - 1</li>')
+        self.assert_equal(stream.next(), u'<li>3 - 2</li><li>4 - 3</li></ul>')
+
+    def test_streaming_behavior(self):
+        tmpl = env.from_string("")
+        stream = tmpl.stream()
+        assert not stream.buffered
+        stream.enable_buffering(20)
+        assert stream.buffered
+        stream.disable_buffering()
+        assert not stream.buffered
+
+
+class UndefinedTestCase(JinjaTestCase):
+
+    def test_stopiteration_is_undefined(self):
+        def test():
+            raise StopIteration()
+        t = Template('A{{ test() }}B')
+        assert t.render(test=test) == 'AB'
+        t = Template('A{{ test().missingattribute }}B')
+        self.assert_raises(UndefinedError, t.render, test=test)
+
+    def test_default_undefined(self):
+        env = Environment(undefined=Undefined)
+        self.assert_equal(env.from_string('{{ missing }}').render(), u'')
+        self.assert_raises(UndefinedError,
+                           env.from_string('{{ missing.attribute }}').render)
+        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
+        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
+        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
+
+    def test_debug_undefined(self):
+        env = Environment(undefined=DebugUndefined)
+        self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
+        self.assert_raises(UndefinedError,
+                           env.from_string('{{ missing.attribute }}').render)
+        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
+        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
+                          u"{{ no such element: int object['missing'] }}")
+        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
+
+    def test_strict_undefined(self):
+        env = Environment(undefined=StrictUndefined)
+        self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
+        self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
+        self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
+        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+        self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
+        self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
+
+    def test_indexing_gives_undefined(self):
+        t = Template("{{ var[42].foo }}")
+        self.assert_raises(UndefinedError, t.render, var=0)
+
+    def test_none_gives_proper_error(self):
+        try:
+            Environment().getattr(None, 'split')()
+        except UndefinedError, e:
+            assert e.message == "'None' has no attribute 'split'"
+        else:
+            assert False, 'expected exception'
+
+    def test_object_repr(self):
+        try:
+            Undefined(obj=42, name='upper')()
+        except UndefinedError, e:
+            assert e.message == "'int object' has no attribute 'upper'"
+        else:
+            assert False, 'expected exception'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
+    suite.addTest(unittest.makeSuite(MetaTestCase))
+    suite.addTest(unittest.makeSuite(StreamingTestCase))
+    suite.addTest(unittest.makeSuite(UndefinedTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py
new file mode 100644
index 0000000..37e3c50
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/core_tags.py
@@ -0,0 +1,286 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.core_tags
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test the core tags like for and if.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
+     DictLoader
+
+env = Environment()
+
+
+class ForLoopTestCase(JinjaTestCase):
+
+    def test_simple(self):
+        tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
+        assert tmpl.render(seq=range(10)) == '0123456789'
+
+    def test_else(self):
+        tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
+        assert tmpl.render() == '...'
+
+    def test_empty_blocks(self):
+        tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
+        assert tmpl.render() == '<>'
+
+    def test_context_vars(self):
+        tmpl = env.from_string('''{% for item in seq -%}
+        {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
+            loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
+           loop.length }}###{% endfor %}''')
+        one, two, _ = tmpl.render(seq=[0, 1]).split('###')
+        (one_index, one_index0, one_revindex, one_revindex0, one_first,
+         one_last, one_length) = one.split('|')
+        (two_index, two_index0, two_revindex, two_revindex0, two_first,
+         two_last, two_length) = two.split('|')
+
+        assert int(one_index) == 1 and int(two_index) == 2
+        assert int(one_index0) == 0 and int(two_index0) == 1
+        assert int(one_revindex) == 2 and int(two_revindex) == 1
+        assert int(one_revindex0) == 1 and int(two_revindex0) == 0
+        assert one_first == 'True' and two_first == 'False'
+        assert one_last == 'False' and two_last == 'True'
+        assert one_length == two_length == '2'
+
+    def test_cycling(self):
+        tmpl = env.from_string('''{% for item in seq %}{{
+            loop.cycle('<1>', '<2>') }}{% endfor %}{%
+            for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
+        output = tmpl.render(seq=range(4), through=('<1>', '<2>'))
+        assert output == '<1><2>' * 4
+
+    def test_scope(self):
+        tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
+        output = tmpl.render(seq=range(10))
+        assert not output
+
+    def test_varlen(self):
+        def inner():
+            for item in range(5):
+                yield item
+        tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}')
+        output = tmpl.render(iter=inner())
+        assert output == '01234'
+
+    def test_noniter(self):
+        tmpl = env.from_string('{% for item in none %}...{% endfor %}')
+        self.assert_raises(TypeError, tmpl.render)
+
+    def test_recursive(self):
+        tmpl = env.from_string('''{% for item in seq recursive -%}
+            [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+        {%- endfor %}''')
+        assert tmpl.render(seq=[
+            dict(a=1, b=[dict(a=1), dict(a=2)]),
+            dict(a=2, b=[dict(a=1), dict(a=2)]),
+            dict(a=3, b=[dict(a='a')])
+        ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
+
+    def test_looploop(self):
+        tmpl = env.from_string('''{% for row in table %}
+            {%- set rowloop = loop -%}
+            {% for cell in row -%}
+                [{{ rowloop.index }}|{{ loop.index }}]
+            {%- endfor %}
+        {%- endfor %}''')
+        assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
+
+    def test_reversed_bug(self):
+        tmpl = env.from_string('{% for i in items %}{{ i }}'
+                               '{% if not loop.last %}'
+                               ',{% endif %}{% endfor %}')
+        assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
+
+    def test_loop_errors(self):
+        tmpl = env.from_string('''{% for item in [1] if loop.index
+                                      == 0 %}...{% endfor %}''')
+        self.assert_raises(UndefinedError, tmpl.render)
+        tmpl = env.from_string('''{% for item in [] %}...{% else
+            %}{{ loop }}{% endfor %}''')
+        assert tmpl.render() == ''
+
+    def test_loop_filter(self):
+        tmpl = env.from_string('{% for item in range(10) if item '
+                               'is even %}[{{ item }}]{% endfor %}')
+        assert tmpl.render() == '[0][2][4][6][8]'
+        tmpl = env.from_string('''
+            {%- for item in range(10) if item is even %}[{{
+                loop.index }}:{{ item }}]{% endfor %}''')
+        assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
+
+    def test_loop_unassignable(self):
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '{% for loop in seq %}...{% endfor %}')
+
+    def test_scoped_special_var(self):
+        t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
+                            '|{{ loop.first }}{% endfor %}]{% endfor %}')
+        assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
+
+    def test_scoped_loop_var(self):
+        t = env.from_string('{% for x in seq %}{{ loop.first }}'
+                            '{% for y in seq %}{% endfor %}{% endfor %}')
+        assert t.render(seq='ab') == 'TrueFalse'
+        t = env.from_string('{% for x in seq %}{% for y in seq %}'
+                            '{{ loop.first }}{% endfor %}{% endfor %}')
+        assert t.render(seq='ab') == 'TrueFalseTrueFalse'
+
+    def test_recursive_empty_loop_iter(self):
+        t = env.from_string('''
+        {%- for item in foo recursive -%}{%- endfor -%}
+        ''')
+        assert t.render(dict(foo=[])) == ''
+
+    def test_call_in_loop(self):
+        t = env.from_string('''
+        {%- macro do_something() -%}
+            [{{ caller() }}]
+        {%- endmacro %}
+
+        {%- for i in [1, 2, 3] %}
+            {%- call do_something() -%}
+                {{ i }}
+            {%- endcall %}
+        {%- endfor -%}
+        ''')
+        assert t.render() == '[1][2][3]'
+
+    def test_scoping_bug(self):
+        t = env.from_string('''
+        {%- for item in foo %}...{{ item }}...{% endfor %}
+        {%- macro item(a) %}...{{ a }}...{% endmacro %}
+        {{- item(2) -}}
+        ''')
+        assert t.render(foo=(1,)) == '...1......2...'
+
+    def test_unpacking(self):
+        tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
+            '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
+        assert tmpl.render() == '1|2|3'
+
+
+class IfConditionTestCase(JinjaTestCase):
+
+    def test_simple(self):
+        tmpl = env.from_string('''{% if true %}...{% endif %}''')
+        assert tmpl.render() == '...'
+
+    def test_elif(self):
+        tmpl = env.from_string('''{% if false %}XXX{% elif true
+            %}...{% else %}XXX{% endif %}''')
+        assert tmpl.render() == '...'
+
+    def test_else(self):
+        tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
+        assert tmpl.render() == '...'
+
+    def test_empty(self):
+        tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
+        assert tmpl.render() == '[]'
+
+    def test_complete(self):
+        tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
+                               'C{% else %}D{% endif %}')
+        assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
+
+    def test_no_scope(self):
+        tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
+        assert tmpl.render(a=True) == '1'
+        tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
+        assert tmpl.render() == '1'
+
+
+class MacrosTestCase(JinjaTestCase):
+    env = Environment(trim_blocks=True)
+
+    def test_simple(self):
+        tmpl = self.env.from_string('''\
+{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
+{{ say_hello('Peter') }}''')
+        assert tmpl.render() == 'Hello Peter!'
+
+    def test_scoping(self):
+        tmpl = self.env.from_string('''\
+{% macro level1(data1) %}
+{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
+{{ level2('bar') }}{% endmacro %}
+{{ level1('foo') }}''')
+        assert tmpl.render() == 'foo|bar'
+
+    def test_arguments(self):
+        tmpl = self.env.from_string('''\
+{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
+{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
+        assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
+
+    def test_varargs(self):
+        tmpl = self.env.from_string('''\
+{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
+{{ test(1, 2, 3) }}''')
+        assert tmpl.render() == '1|2|3'
+
+    def test_simple_call(self):
+        tmpl = self.env.from_string('''\
+{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
+{% call test() %}data{% endcall %}''')
+        assert tmpl.render() == '[[data]]'
+
+    def test_complex_call(self):
+        tmpl = self.env.from_string('''\
+{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
+{% call(data) test() %}{{ data }}{% endcall %}''')
+        assert tmpl.render() == '[[data]]'
+
+    def test_caller_undefined(self):
+        tmpl = self.env.from_string('''\
+{% set caller = 42 %}\
+{% macro test() %}{{ caller is not defined }}{% endmacro %}\
+{{ test() }}''')
+        assert tmpl.render() == 'True'
+
+    def test_include(self):
+        self.env = Environment(loader=DictLoader({'include':
+            '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
+        tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
+        assert tmpl.render() == '[foo]'
+
+    def test_macro_api(self):
+        tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
+                               '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
+                               '{% macro baz() %}{{ caller() }}{% endmacro %}')
+        assert tmpl.module.foo.arguments == ('a', 'b')
+        assert tmpl.module.foo.defaults == ()
+        assert tmpl.module.foo.name == 'foo'
+        assert not tmpl.module.foo.caller
+        assert not tmpl.module.foo.catch_kwargs
+        assert not tmpl.module.foo.catch_varargs
+        assert tmpl.module.bar.arguments == ()
+        assert tmpl.module.bar.defaults == ()
+        assert not tmpl.module.bar.caller
+        assert tmpl.module.bar.catch_kwargs
+        assert tmpl.module.bar.catch_varargs
+        assert tmpl.module.baz.caller
+
+    def test_callself(self):
+        tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
+                                    '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
+                                    '{{ foo(5) }}')
+        assert tmpl.render() == '5|4|3|2|1'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ForLoopTestCase))
+    suite.addTest(unittest.makeSuite(IfConditionTestCase))
+    suite.addTest(unittest.makeSuite(MacrosTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py
new file mode 100644
index 0000000..55be94a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/debug.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.debug
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests the debug system.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import sys
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase, filesystem_loader
+
+from ambari_jinja2 import Environment, TemplateSyntaxError
+
+env = Environment(loader=filesystem_loader)
+
+
+class DebugTestCase(JinjaTestCase):
+
+    if sys.version_info[:2] != (2, 4):
+        def test_runtime_error(self):
+            def test():
+                tmpl.render(fail=lambda: 1 / 0)
+            tmpl = env.get_template('broken.html')
+            self.assert_traceback_matches(test, r'''
+  File ".*?broken.html", line 2, in (top-level template code|<module>)
+    \{\{ fail\(\) \}\}
+  File ".*?debug.pyc?", line \d+, in <lambda>
+    tmpl\.render\(fail=lambda: 1 / 0\)
+ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
+''')
+
+    def test_syntax_error(self):
+        # XXX: the .*? is necessary for python3 which does not hide
+        # some of the stack frames we don't want to show.  Not sure
+        # what's up with that, but that is not that critical.  Should
+        # be fixed though.
+        self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
+  File ".*?syntaxerror.html", line 4, in (template|<module>)
+    \{% endif %\}.*?
+(ambari_jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
+    ''')
+
+    def test_regular_syntax_error(self):
+        def test():
+            raise TemplateSyntaxError('wtf', 42)
+        self.assert_traceback_matches(test, r'''
+  File ".*debug.pyc?", line \d+, in test
+    raise TemplateSyntaxError\('wtf', 42\)
+(ambari_jinja2\.exceptions\.)?TemplateSyntaxError: wtf
+  line 42''')
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(DebugTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py
new file mode 100644
index 0000000..72ddde5
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/doctests.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.doctests
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    The doctests.  Collects all tests we want to test from
+    the Jinja modules.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import unittest
+import doctest
+
+
+def suite():
+    from ambari_jinja2 import utils, sandbox, runtime, meta, loaders, \
+        ext, environment, bccache, nodes
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocTestSuite(utils))
+    suite.addTest(doctest.DocTestSuite(sandbox))
+    suite.addTest(doctest.DocTestSuite(runtime))
+    suite.addTest(doctest.DocTestSuite(meta))
+    suite.addTest(doctest.DocTestSuite(loaders))
+    suite.addTest(doctest.DocTestSuite(ext))
+    suite.addTest(doctest.DocTestSuite(environment))
+    suite.addTest(doctest.DocTestSuite(bccache))
+    suite.addTest(doctest.DocTestSuite(nodes))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py
new file mode 100644
index 0000000..8a9a8d9
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/ext.py
@@ -0,0 +1,455 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.ext
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Tests for the extensions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase, filesystem_loader
+
+from ambari_jinja2 import Environment, DictLoader, contextfunction, nodes
+from ambari_jinja2.exceptions import TemplateAssertionError
+from ambari_jinja2.ext import Extension
+from ambari_jinja2.lexer import Token, count_newlines
+from ambari_jinja2.utils import next
+
+# 2.x / 3.x
+try:
+    from io import BytesIO
+except ImportError:
+    from StringIO import StringIO as BytesIO
+
+
+importable_object = 23
+
+_gettext_re = re.compile(r'_\((.*?)\)(?s)')
+
+
+i18n_templates = {
+    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+                   '{% block body %}{% endblock %}',
+    'child.html': '{% extends "master.html" %}{% block body %}'
+                  '{% trans %}watch out{% endtrans %}{% endblock %}',
+    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+                   '{{ user_count }} users online{% endtrans %}',
+    'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}'
+}
+
+newstyle_i18n_templates = {
+    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+                   '{% block body %}{% endblock %}',
+    'child.html': '{% extends "master.html" %}{% block body %}'
+                  '{% trans %}watch out{% endtrans %}{% endblock %}',
+    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+                   '{{ user_count }} users online{% endtrans %}',
+    'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}',
+    'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}',
+    'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}'
+                          '{{ num }} apples{% endtrans %}',
+    'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}',
+    'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}',
+    'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}',
+    'novars.html': '{% trans %}%(hello)s{% endtrans %}',
+    'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}',
+    'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}'
+}
+
+
+languages = {
+    'de': {
+        'missing':                      u'fehlend',
+        'watch out':                    u'pass auf',
+        'One user online':              u'Ein Benutzer online',
+        '%(user_count)s users online':  u'%(user_count)s Benutzer online',
+        'User: %(num)s':                u'Benutzer: %(num)s',
+        'User: %(count)s':              u'Benutzer: %(count)s',
+        '%(num)s apple':                u'%(num)s Apfel',
+        '%(num)s apples':               u'%(num)s Äpfel'
+    }
+}
+
+
+@contextfunction
+def gettext(context, string):
+    language = context.get('LANGUAGE', 'en')
+    return languages.get(language, {}).get(string, string)
+
+
+@contextfunction
+def ngettext(context, s, p, n):
+    language = context.get('LANGUAGE', 'en')
+    if n != 1:
+        return languages.get(language, {}).get(p, p)
+    return languages.get(language, {}).get(s, s)
+
+
+i18n_env = Environment(
+    loader=DictLoader(i18n_templates),
+    extensions=['ambari_jinja2.ext.i18n']
+)
+i18n_env.globals.update({
+    '_':            gettext,
+    'gettext':      gettext,
+    'ngettext':     ngettext
+})
+
+newstyle_i18n_env = Environment(
+    loader=DictLoader(newstyle_i18n_templates),
+    extensions=['ambari_jinja2.ext.i18n']
+)
+newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
+
+class TestExtension(Extension):
+    tags = set(['test'])
+    ext_attr = 42
+
+    def parse(self, parser):
+        return nodes.Output([self.call_method('_dump', [
+            nodes.EnvironmentAttribute('sandboxed'),
+            self.attr('ext_attr'),
+            nodes.ImportedName(__name__ + '.importable_object'),
+            nodes.ContextReference()
+        ])]).set_lineno(next(parser.stream).lineno)
+
+    def _dump(self, sandboxed, ext_attr, imported_object, context):
+        return '%s|%s|%s|%s' % (
+            sandboxed,
+            ext_attr,
+            imported_object,
+            context.blocks
+        )
+
+
+class PreprocessorExtension(Extension):
+
+    def preprocess(self, source, name, filename=None):
+        return source.replace('[[TEST]]', '({{ foo }})')
+
+
+class StreamFilterExtension(Extension):
+
+    def filter_stream(self, stream):
+        for token in stream:
+            if token.type == 'data':
+                for t in self.interpolate(token):
+                    yield t
+            else:
+                yield token
+
+    def interpolate(self, token):
+        pos = 0
+        end = len(token.value)
+        lineno = token.lineno
+        while 1:
+            match = _gettext_re.search(token.value, pos)
+            if match is None:
+                break
+            value = token.value[pos:match.start()]
+            if value:
+                yield Token(lineno, 'data', value)
+            lineno += count_newlines(token.value)
+            yield Token(lineno, 'variable_begin', None)
+            yield Token(lineno, 'name', 'gettext')
+            yield Token(lineno, 'lparen', None)
+            yield Token(lineno, 'string', match.group(1))
+            yield Token(lineno, 'rparen', None)
+            yield Token(lineno, 'variable_end', None)
+            pos = match.end()
+        if pos < end:
+            yield Token(lineno, 'data', token.value[pos:])
+
+
+class ExtensionsTestCase(JinjaTestCase):
+
+    def test_extend_late(self):
+        env = Environment()
+        env.add_extension('ambari_jinja2.ext.autoescape')
+        t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
+        assert t.render() == '&lt;test&gt;'
+
+    def test_loop_controls(self):
+        env = Environment(extensions=['ambari_jinja2.ext.loopcontrols'])
+
+        tmpl = env.from_string('''
+            {%- for item in [1, 2, 3, 4] %}
+                {%- if item % 2 == 0 %}{% continue %}{% endif -%}
+                {{ item }}
+            {%- endfor %}''')
+        assert tmpl.render() == '13'
+
+        tmpl = env.from_string('''
+            {%- for item in [1, 2, 3, 4] %}
+                {%- if item > 2 %}{% break %}{% endif -%}
+                {{ item }}
+            {%- endfor %}''')
+        assert tmpl.render() == '12'
+
+    def test_do(self):
+        env = Environment(extensions=['ambari_jinja2.ext.do'])
+        tmpl = env.from_string('''
+            {%- set items = [] %}
+            {%- for char in "foo" %}
+                {%- do items.append(loop.index0 ~ char) %}
+            {%- endfor %}{{ items|join(', ') }}''')
+        assert tmpl.render() == '0f, 1o, 2o'
+
+    def test_with(self):
+        env = Environment(extensions=['ambari_jinja2.ext.with_'])
+        tmpl = env.from_string('''\
+        {% with a=42, b=23 -%}
+            {{ a }} = {{ b }}
+        {% endwith -%}
+            {{ a }} = {{ b }}\
+        ''')
+        assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
+            == ['42 = 23', '1 = 2']
+
+    def test_extension_nodes(self):
+        env = Environment(extensions=[TestExtension])
+        tmpl = env.from_string('{% test %}')
+        assert tmpl.render() == 'False|42|23|{}'
+
+    def test_identifier(self):
+        assert TestExtension.identifier == __name__ + '.TestExtension'
+
+    def test_rebinding(self):
+        original = Environment(extensions=[TestExtension])
+        overlay = original.overlay()
+        for env in original, overlay:
+            for ext in env.extensions.itervalues():
+                assert ext.environment is env
+
+    def test_preprocessor_extension(self):
+        env = Environment(extensions=[PreprocessorExtension])
+        tmpl = env.from_string('{[[TEST]]}')
+        assert tmpl.render(foo=42) == '{(42)}'
+
+    def test_streamfilter_extension(self):
+        env = Environment(extensions=[StreamFilterExtension])
+        env.globals['gettext'] = lambda x: x.upper()
+        tmpl = env.from_string('Foo _(bar) Baz')
+        out = tmpl.render()
+        assert out == 'Foo BAR Baz'
+
+    def test_extension_ordering(self):
+        class T1(Extension):
+            priority = 1
+        class T2(Extension):
+            priority = 2
+        env = Environment(extensions=[T1, T2])
+        ext = list(env.iter_extensions())
+        assert ext[0].__class__ is T1
+        assert ext[1].__class__ is T2
+
+
+class InternationalizationTestCase(JinjaTestCase):
+
+    def test_trans(self):
+        tmpl = i18n_env.get_template('child.html')
+        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+    def test_trans_plural(self):
+        tmpl = i18n_env.get_template('plural.html')
+        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+    def test_complex_plural(self):
+        tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
+                                    'pluralize count %}{{ count }} items{% endtrans %}')
+        assert tmpl.render() == '2 items'
+        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
+                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+    def test_trans_stringformatting(self):
+        tmpl = i18n_env.get_template('stringformat.html')
+        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+    def test_extract(self):
+        from ambari_jinja2.ext import babel_extract
+        source = BytesIO('''
+        {{ gettext('Hello World') }}
+        {% trans %}Hello World{% endtrans %}
+        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+        '''.encode('ascii')) # make python 3 happy
+        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
+            (2, 'gettext', u'Hello World', []),
+            (3, 'gettext', u'Hello World', []),
+            (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
+        ]
+
+    def test_comment_extract(self):
+        from ambari_jinja2.ext import babel_extract
+        source = BytesIO('''
+        {# trans first #}
+        {{ gettext('Hello World') }}
+        {% trans %}Hello World{% endtrans %}{# trans second #}
+        {#: third #}
+        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+        '''.encode('utf-8')) # make python 3 happy
+        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
+            (3, 'gettext', u'Hello World', ['first']),
+            (4, 'gettext', u'Hello World', ['second']),
+            (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
+        ]
+
+
+class NewstyleInternationalizationTestCase(JinjaTestCase):
+
+    def test_trans(self):
+        tmpl = newstyle_i18n_env.get_template('child.html')
+        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+    def test_trans_plural(self):
+        tmpl = newstyle_i18n_env.get_template('plural.html')
+        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+    def test_complex_plural(self):
+        tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
+                                    'pluralize count %}{{ count }} items{% endtrans %}')
+        assert tmpl.render() == '2 items'
+        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
+                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+    def test_trans_stringformatting(self):
+        tmpl = newstyle_i18n_env.get_template('stringformat.html')
+        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+    def test_newstyle_plural(self):
+        tmpl = newstyle_i18n_env.get_template('ngettext.html')
+        assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel'
+        assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel'
+
+    def test_autoescape_support(self):
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape',
+                                      'ambari_jinja2.ext.i18n'])
+        env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
+                                      lambda s, p, n: s, newstyle=True)
+        t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
+                            '"<test>") }}{% endautoescape %}')
+        assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
+        assert t.render(ae=False) == '<strong>Wert: <test></strong>'
+
+    def test_num_used_twice(self):
+        tmpl = newstyle_i18n_env.get_template('ngettext_long.html')
+        assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Äpfel'
+
+    def test_num_called_num(self):
+        source = newstyle_i18n_env.compile('''
+            {% trans num=3 %}{{ num }} apple{% pluralize
+            %}{{ num }} apples{% endtrans %}
+        ''', raw=True)
+        # quite hacky, but the only way to properly test that.  The idea is
+        # that the generated code does not pass num twice (although that
+        # would work) for better performance.  This only works on the
+        # newstyle gettext of course
+        assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s "
+                         r"apples', 3", source) is not None
+
+    def test_trans_vars(self):
+        t1 = newstyle_i18n_env.get_template('transvars1.html')
+        t2 = newstyle_i18n_env.get_template('transvars2.html')
+        t3 = newstyle_i18n_env.get_template('transvars3.html')
+        assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1'
+        assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23'
+        assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42'
+
+    def test_novars_vars_escaping(self):
+        t = newstyle_i18n_env.get_template('novars.html')
+        assert t.render() == '%(hello)s'
+        t = newstyle_i18n_env.get_template('vars.html')
+        assert t.render(foo='42') == '42%(foo)s'
+        t = newstyle_i18n_env.get_template('explicitvars.html')
+        assert t.render() == '%(foo)s'
+
+
+class AutoEscapeTestCase(JinjaTestCase):
+
+    def test_scoped_setting(self):
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
+                          autoescape=True)
+        tmpl = env.from_string('''
+            {{ "<HelloWorld>" }}
+            {% autoescape false %}
+                {{ "<HelloWorld>" }}
+            {% endautoescape %}
+            {{ "<HelloWorld>" }}
+        ''')
+        assert tmpl.render().split() == \
+            [u'&lt;HelloWorld&gt;', u'<HelloWorld>', u'&lt;HelloWorld&gt;']
+
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
+                          autoescape=False)
+        tmpl = env.from_string('''
+            {{ "<HelloWorld>" }}
+            {% autoescape true %}
+                {{ "<HelloWorld>" }}
+            {% endautoescape %}
+            {{ "<HelloWorld>" }}
+        ''')
+        assert tmpl.render().split() == \
+            [u'<HelloWorld>', u'&lt;HelloWorld&gt;', u'<HelloWorld>']
+
+    def test_nonvolatile(self):
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
+                          autoescape=True)
+        tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}')
+        assert tmpl.render() == ' foo="&lt;test&gt;"'
+        tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}'
+                               '|xmlattr|escape }}{% endautoescape %}')
+        assert tmpl.render() == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+
+    def test_volatile(self):
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
+                          autoescape=True)
+        tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}'
+                               '|xmlattr|escape }}{% endautoescape %}')
+        assert tmpl.render(foo=False) == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+        assert tmpl.render(foo=True) == ' foo="&lt;test&gt;"'
+
+    def test_scoping(self):
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'])
+        tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
+                               '{% endautoescape %}{{ x }}{{ "<y>" }}')
+        assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
+
+    def test_volatile_scoping(self):
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'])
+        tmplsource = '''
+        {% autoescape val %}
+            {% macro foo(x) %}
+                [{{ x }}]
+            {% endmacro %}
+            {{ foo().__class__.__name__ }}
+        {% endautoescape %}
+        {{ '<testing>' }}
+        '''
+        tmpl = env.from_string(tmplsource)
+        assert tmpl.render(val=True).split()[0] == 'Markup'
+        assert tmpl.render(val=False).split()[0] == unicode.__name__
+
+        # looking at the source we should see <testing> there in raw
+        # (and then escaped as well)
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'])
+        pysource = env.compile(tmplsource, raw=True)
+        assert '<testing>\\n' in pysource
+
+        env = Environment(extensions=['ambari_jinja2.ext.autoescape'],
+                          autoescape=True)
+        pysource = env.compile(tmplsource, raw=True)
+        assert '&lt;testing&gt;\\n' in pysource
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ExtensionsTestCase))
+    suite.addTest(unittest.makeSuite(InternationalizationTestCase))
+    suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
+    suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py
new file mode 100644
index 0000000..9d0b098
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/filters.py
@@ -0,0 +1,291 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.filters
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests for the jinja filters.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import unittest
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Markup, Environment
+
+env = Environment()
+
+
+class FilterTestCase(JinjaTestCase):
+
+    def test_capitalize(self):
+        tmpl = env.from_string('{{ "foo bar"|capitalize }}')
+        assert tmpl.render() == 'Foo bar'
+
+    def test_center(self):
+        tmpl = env.from_string('{{ "foo"|center(9) }}')
+        assert tmpl.render() == '   foo   '
+
+    def test_default(self):
+        tmpl = env.from_string(
+            "{{ missing|default('no') }}|{{ false|default('no') }}|"
+            "{{ false|default('no', true) }}|{{ given|default('no') }}"
+        )
+        assert tmpl.render(given='yes') == 'no|False|no|yes'
+
+    def test_dictsort(self):
+        tmpl = env.from_string(
+            '{{ foo|dictsort }}|'
+            '{{ foo|dictsort(true) }}|'
+            '{{ foo|dictsort(false, "value") }}'
+        )
+        out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
+        assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
+                       "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
+                       "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
+
+    def test_batch(self):
+        tmpl = env.from_string("{{ foo|batch(3)|list }}|"
+                               "{{ foo|batch(3, 'X')|list }}")
+        out = tmpl.render(foo=range(10))
+        assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
+                       "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
+
+    def test_slice(self):
+        tmpl = env.from_string('{{ foo|slice(3)|list }}|'
+                               '{{ foo|slice(3, "X")|list }}')
+        out = tmpl.render(foo=range(10))
+        assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
+                       "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
+
+    def test_escape(self):
+        tmpl = env.from_string('''{{ '<">&'|escape }}''')
+        out = tmpl.render()
+        assert out == '&lt;&#34;&gt;&amp;'
+
+    def test_striptags(self):
+        tmpl = env.from_string('''{{ foo|striptags }}''')
+        out = tmpl.render(foo='  <p>just a small   \n <a href="#">'
+                          'example</a> link</p>\n<p>to a webpage</p> '
+                          '<!-- <p>and some commented stuff</p> -->')
+        assert out == 'just a small example link to a webpage'
+
+    def test_filesizeformat(self):
+        tmpl = env.from_string(
+            '{{ 100|filesizeformat }}|'
+            '{{ 1000|filesizeformat }}|'
+            '{{ 1000000|filesizeformat }}|'
+            '{{ 1000000000|filesizeformat }}|'
+            '{{ 1000000000000|filesizeformat }}|'
+            '{{ 100|filesizeformat(true) }}|'
+            '{{ 1000|filesizeformat(true) }}|'
+            '{{ 1000000|filesizeformat(true) }}|'
+            '{{ 1000000000|filesizeformat(true) }}|'
+            '{{ 1000000000000|filesizeformat(true) }}'
+        )
+        out = tmpl.render()
+        assert out == (
+            '100 Bytes|1.0 KB|1.0 MB|1.0 GB|1000.0 GB|'
+            '100 Bytes|1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
+        )
+
+    def test_first(self):
+        tmpl = env.from_string('{{ foo|first }}')
+        out = tmpl.render(foo=range(10))
+        assert out == '0'
+
+    def test_float(self):
+        tmpl = env.from_string('{{ "42"|float }}|'
+                               '{{ "ajsghasjgd"|float }}|'
+                               '{{ "32.32"|float }}')
+        out = tmpl.render()
+        assert out == '42.0|0.0|32.32'
+
+    def test_format(self):
+        tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
+        out = tmpl.render()
+        assert out == 'a|b'
+
+    def test_indent(self):
+        tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
+        text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
+        out = tmpl.render(foo=text)
+        assert out == ('foo bar foo bar\n  foo bar foo bar|  '
+                       'foo bar foo bar\n  foo bar foo bar')
+
+    def test_int(self):
+        tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
+                               '{{ "32.32"|int }}')
+        out = tmpl.render()
+        assert out == '42|0|32'
+
+    def test_join(self):
+        tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
+        out = tmpl.render()
+        assert out == '1|2|3'
+
+        env2 = Environment(autoescape=True)
+        tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
+        assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
+
+    def test_last(self):
+        tmpl = env.from_string('''{{ foo|last }}''')
+        out = tmpl.render(foo=range(10))
+        assert out == '9'
+
+    def test_length(self):
+        tmpl = env.from_string('''{{ "hello world"|length }}''')
+        out = tmpl.render()
+        assert out == '11'
+
+    def test_lower(self):
+        tmpl = env.from_string('''{{ "FOO"|lower }}''')
+        out = tmpl.render()
+        assert out == 'foo'
+
+    def test_pprint(self):
+        from pprint import pformat
+        tmpl = env.from_string('''{{ data|pprint }}''')
+        data = range(1000)
+        assert tmpl.render(data=data) == pformat(data)
+
+    def test_random(self):
+        tmpl = env.from_string('''{{ seq|random }}''')
+        seq = range(100)
+        for _ in range(10):
+            assert int(tmpl.render(seq=seq)) in seq
+
+    def test_reverse(self):
+        tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
+                               '{{ [1, 2, 3]|reverse|list }}')
+        assert tmpl.render() == 'raboof|[3, 2, 1]'
+
+    def test_string(self):
+        x = [1, 2, 3, 4, 5]
+        tmpl = env.from_string('''{{ obj|string }}''')
+        assert tmpl.render(obj=x) == unicode(x)
+
+    def test_title(self):
+        tmpl = env.from_string('''{{ "foo bar"|title }}''')
+        assert tmpl.render() == "Foo Bar"
+
+    def test_truncate(self):
+        tmpl = env.from_string(
+            '{{ data|truncate(15, true, ">>>") }}|'
+            '{{ data|truncate(15, false, ">>>") }}|'
+            '{{ smalldata|truncate(15) }}'
+        )
+        out = tmpl.render(data='foobar baz bar' * 1000,
+                          smalldata='foobar baz bar')
+        assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar'
+
+    def test_upper(self):
+        tmpl = env.from_string('{{ "foo"|upper }}')
+        assert tmpl.render() == 'FOO'
+
+    def test_urlize(self):
+        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
+        assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
+                                'http://www.example.com/</a> bar'
+
+    def test_wordcount(self):
+        tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
+        assert tmpl.render() == '3'
+
+    def test_block(self):
+        tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
+        assert tmpl.render() == '&lt;hehe&gt;'
+
+    def test_chaining(self):
+        tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
+        assert tmpl.render() == '&lt;FOO&gt;'
+
+    def test_sum(self):
+        tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
+        assert tmpl.render() == '21'
+
+    def test_abs(self):
+        tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
+        assert tmpl.render() == '1|1', tmpl.render()
+
+    def test_round_positive(self):
+        tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
+                               "{{ 2.1234|round(3, 'floor') }}|"
+                               "{{ 2.1|round(0, 'ceil') }}")
+        assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
+
+    def test_round_negative(self):
+        tmpl = env.from_string('{{ 21.3|round(-1)}}|'
+                               "{{ 21.3|round(-1, 'ceil')}}|"
+                               "{{ 21.3|round(-1, 'floor')}}")
+        assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
+
+    def test_xmlattr(self):
+        tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
+                               "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
+        out = tmpl.render().split()
+        assert len(out) == 3
+        assert 'foo="42"' in out
+        assert 'bar="23"' in out
+        assert 'blub:blub="&lt;?&gt;"' in out
+
+    def test_sort1(self):
+        tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
+        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+    def test_sort2(self):
+        tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort(false, true)) }}')
+        assert tmpl.render() == 'AbcD'
+
+    def test_groupby(self):
+        tmpl = env.from_string('''
+        {%- for grouper, list in [{'foo': 1, 'bar': 2},
+                                  {'foo': 2, 'bar': 3},
+                                  {'foo': 1, 'bar': 1},
+                                  {'foo': 3, 'bar': 4}]|groupby('foo') -%}
+            {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
+        {%- endfor %}''')
+        assert tmpl.render().split('|') == [
+            "1: 1, 2: 1, 1",
+            "2: 2, 3",
+            "3: 3, 4",
+            ""
+        ]
+
+    def test_filtertag(self):
+        tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
+                               "foobar{% endfilter %}")
+        assert tmpl.render() == 'fooBAR'
+
+    def test_replace(self):
+        env = Environment()
+        tmpl = env.from_string('{{ string|replace("o", 42) }}')
+        assert tmpl.render(string='<foo>') == '<f4242>'
+        env = Environment(autoescape=True)
+        tmpl = env.from_string('{{ string|replace("o", 42) }}')
+        assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
+        tmpl = env.from_string('{{ string|replace("<", 42) }}')
+        assert tmpl.render(string='<foo>') == '42foo&gt;'
+        tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
+        assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
+
+    def test_forceescape(self):
+        tmpl = env.from_string('{{ x|forceescape }}')
+        assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
+
+    def test_safe(self):
+        env = Environment(autoescape=True)
+        tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
+        assert tmpl.render() == '<div>foo</div>'
+        tmpl = env.from_string('{{ "<div>foo</div>" }}')
+        assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
+
+    def test_sort2(self):
+        tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
+        assert tmpl.render() == "['Bar', 'blah', 'foo']"
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(FilterTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py
new file mode 100644
index 0000000..799daf1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/imports.py
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.imports
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests the import features (with includes).
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment, DictLoader
+from ambari_jinja2.exceptions import TemplateNotFound, TemplatesNotFound
+
+
+test_env = Environment(loader=DictLoader(dict(
+    module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
+    header='[{{ foo }}|{{ 23 }}]',
+    o_printer='({{ o }})'
+)))
+test_env.globals['bar'] = 23
+
+
+class ImportsTestCase(JinjaTestCase):
+
+    def test_context_imports(self):
+        t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
+        assert t.render(foo=42) == '[42|23]'
+        t = test_env.from_string('{% from "module" import test %}{{ test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
+        assert t.render(foo=42) == '[42|23]'
+
+    def test_trailing_comma(self):
+        test_env.from_string('{% from "foo" import bar, baz with context %}')
+        test_env.from_string('{% from "foo" import bar, baz, with context %}')
+        test_env.from_string('{% from "foo" import bar, with context %}')
+        test_env.from_string('{% from "foo" import bar, with, context %}')
+        test_env.from_string('{% from "foo" import bar, with with context %}')
+
+    def test_exports(self):
+        m = test_env.from_string('''
+            {% macro toplevel() %}...{% endmacro %}
+            {% macro __private() %}...{% endmacro %}
+            {% set variable = 42 %}
+            {% for item in [1] %}
+                {% macro notthere() %}{% endmacro %}
+            {% endfor %}
+        ''').module
+        assert m.toplevel() == '...'
+        assert not hasattr(m, '__missing')
+        assert m.variable == 42
+        assert not hasattr(m, 'notthere')
+
+
+class IncludesTestCase(JinjaTestCase):
+
+    def test_context_include(self):
+        t = test_env.from_string('{% include "header" %}')
+        assert t.render(foo=42) == '[42|23]'
+        t = test_env.from_string('{% include "header" with context %}')
+        assert t.render(foo=42) == '[42|23]'
+        t = test_env.from_string('{% include "header" without context %}')
+        assert t.render(foo=42) == '[|23]'
+
+    def test_choice_includes(self):
+        t = test_env.from_string('{% include ["missing", "header"] %}')
+        assert t.render(foo=42) == '[42|23]'
+
+        t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
+        assert t.render(foo=42) == ''
+
+        t = test_env.from_string('{% include ["missing", "missing2"] %}')
+        self.assert_raises(TemplateNotFound, t.render)
+        try:
+            t.render()
+        except TemplatesNotFound, e:
+            assert e.templates == ['missing', 'missing2']
+            assert e.name == 'missing2'
+        else:
+            assert False, 'thou shalt raise'
+
+        def test_includes(t, **ctx):
+            ctx['foo'] = 42
+            assert t.render(ctx) == '[42|23]'
+
+        t = test_env.from_string('{% include ["missing", "header"] %}')
+        test_includes(t)
+        t = test_env.from_string('{% include x %}')
+        test_includes(t, x=['missing', 'header'])
+        t = test_env.from_string('{% include [x, "header"] %}')
+        test_includes(t, x='missing')
+        t = test_env.from_string('{% include x %}')
+        test_includes(t, x='header')
+        t = test_env.from_string('{% include x %}')
+        test_includes(t, x='header')
+        t = test_env.from_string('{% include [x] %}')
+        test_includes(t, x='header')
+
+    def test_include_ignoring_missing(self):
+        t = test_env.from_string('{% include "missing" %}')
+        self.assert_raises(TemplateNotFound, t.render)
+        for extra in '', 'with context', 'without context':
+            t = test_env.from_string('{% include "missing" ignore missing ' +
+                                     extra + ' %}')
+            assert t.render() == ''
+
+    def test_context_include_with_overrides(self):
+        env = Environment(loader=DictLoader(dict(
+            main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
+            item="{{ item }}"
+        )))
+        assert env.get_template("main").render() == "123"
+
+    def test_unoptimized_scopes(self):
+        t = test_env.from_string("""
+            {% macro outer(o) %}
+            {% macro inner() %}
+            {% include "o_printer" %}
+            {% endmacro %}
+            {{ inner() }}
+            {% endmacro %}
+            {{ outer("FOO") }}
+        """)
+        assert t.render().strip() == '(FOO)'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ImportsTestCase))
+    suite.addTest(unittest.makeSuite(IncludesTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py
new file mode 100644
index 0000000..e0666e5
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/testsuite/inheritance.py
@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.testsuite.inheritance
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests the template inheritance feature.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from ambari_jinja2.testsuite import JinjaTestCase
+
+from ambari_jinja2 import Environment, DictLoader
+from ambari_jinja2.exceptions import TemplateSyntaxError
+
+
+LAYOUTTEMPLATE = '''\
+|{% block block1 %}block 1 from layout{% endblock %}
+|{% block block2 %}block 2 from layout{% endblock %}
+|{% block block3 %}
+{% block block4 %}nested block 4 from layout{% endblock %}
+{% endblock %}|'''
+
+LEVEL1TEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}block 1 from level1{% endblock %}'''
+
+LEVEL2TEMPLATE = '''\
+{% extends "level1" %}
+{% block block2 %}{% block block5 %}nested block 5 from level2{%
+endblock %}{% endblock %}'''
+
+LEVEL3TEMPLATE = '''\
+{% extends "level2" %}
+{% block block5 %}block 5 from level3{% endblock %}
+{% block block4 %}block 4 from level3{% endblock %}
+'''
+
+LEVEL4TEMPLATE = '''\
+{% extends "level3" %}
+{% block block3 %}block 3 from level4{% endblock %}
+'''
+
+WORKINGTEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}
+  {% if false %}
+    {% block block2 %}
+      this should workd
+    {% endblock %}
+  {% endif %}
+{% endblock %}
+'''
+
+env = Environment(loader=DictLoader({
+    'layout':       LAYOUTTEMPLATE,
+    'level1':       LEVEL1TEMPLATE,
+    'level2':       LEVEL2TEMPLATE,
+    'level3':       LEVEL3TEMPLATE,
+    'level4':       LEVEL4TEMPLATE,
+    'working':      WORKINGTEMPLATE
+}), trim_blocks=True)
+
+
+class InheritanceTestCase(JinjaTestCase):
+
+    def test_layout(self):
+        tmpl = env.get_template('layout')
+        assert tmpl.render() == ('|block 1 from layout|block 2 from '
+                                 'layout|nested block 4 from layout|')
+
+    def test_level1(self):
+        tmpl = env.get_template('level1')
+        assert tmpl.render() == ('|block 1 from level1|block 2 from '
+                                 'layout|nested block 4 from layout|')
+
+    def test_level2(self):
+        tmpl = env.get_template('level2')
+        assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
+                                 'level2|nested block 4 from layout|')
+
+    def test_level3(self):
+        tmpl = env.get_template('level3')
+        assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
+                                 'block 4 from level3|')
+
+    def test_level4(sel):
+        tmpl = env.get_template('level4')
+        assert tmpl.render() == ('|block 1 from level1|block 5 from '
+                                 'level3|block 3 from level4|')
+
+    def test_super(self):
+        env = Environment(loader=DictLoader({
+            'a': '{% block intro %}INTRO{% endblock %}|'
+                 'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
+            'b': '{% extends "a" %}{% block data %}({{ '
+                 'super() }}){% endblock %}',
+            'c': '{% extends "b" %}{% block intro %}--{{ '
+                 'super() }}--{% endblock %}\n{% block data '
+                 '%}[{{ super() }}]{% endblock %}'
+        }))
+        tmpl = env.get_template('c')
+        assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
+
+    def test_working(self):
+        tmpl = env.get_template('working')
+
+    def test_reuse_blocks(self):
+        tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
+                               '{% endblock %}|{{ self.foo() }}')
+        assert tmpl.render() == '42|42|42'
+
+    def test_preserve_blocks(self):
+        env = Environment(loader=DictLoader({
+            'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
+            'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
+        }))
+        tmpl = env.get_template('b')
+        assert tmpl.render() == 'BA'
+
+    def test_dynamic_inheritance(self):
+        env = Environment(loader=DictLoader({
+            'master1': 'MASTER1{% block x %}{% endblock %}',
+            'master2': 'MASTER2{% block x %}{% endblock %}',
+            'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
+        }))
+        tmpl = env.get_template('child')
+        for m in range(1, 3):
+            assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
+
+    def test_multi_inheritance(self):
+        env = Environment(loader=DictLoader({
+            'master1': 'MASTER1{% block x %}{% endblock %}',
+            'master2': 'MASTER2{% block x %}{% endblock %}',
+            'child': '''{% if master %}{% extends master %}{% else %}{% extends
+                        'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
+        }))
+        tmpl = env.get_template('child')
+        assert tmpl.render(master='master2') == 'MASTER2CHILD'
+        assert tmpl.render(master='master1') == 'MASTER1CHILD'
+        assert tmpl.render() == 'MASTER1CHILD'
+
+    def test_scoped_block(self):
+        env = Environment(loader=DictLoader({
+            'master.html': '{% for item in seq %}[{% block item scoped %}'
+                           '{% endblock %}]{% endfor %}'
+        }))
+        t = env.from_string('{% extends "master.html" %}{% block item %}'
+                            '{{ item }}{% endblock %}')
+        assert t.render(seq=range(5)) == '[0][1][2][3][4]'
+
+    def test_super_in_scoped_block(self):
+        env = Environment(loader=DictLoader({
+            'master.html': '{% for item in seq %}[{% block item scoped %}'
+                           '{{ item }}{% endblock %}]{% endfor %}'
+        }))
+        t = env.from_string('{% extends "master.html" %}{% block item %}'
+                            '{{ super() }}|{{ item * 2 }}{% endblock %}')
+        assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]'
+
+
+class BugFixTestCase(JinjaTestCase):
+
+    def test_fixed_macro_scoping_bug(self):
+        assert Environment(loader=DictLoader({
+            'test.html': '''\
+        {% extends 'details.html' %}
+
+        {% macro my_macro() %}
+        my_macro
+        {% endmacro %}
+
+        {% block inner_box %}
+            {{ my_macro() }}
+        {% endblock %}
+            ''',
+            'details.html': '''\
+        {% extends 'standard.html' %}
+
+        {% macro my_macro() %}
+        my_macro
+        {% endmacro %}
+
+        {% block content %}
+            {% block outer_box %}
+                outer_box
+                {% block inner_box %}
+                    inner_box
+                {% endblock %}
+            {% endblock %}
+        {% endblock %}
+        ''',
+            'standard.html': '''
+        {% block content %}&nbsp;{% endblock %}
+        '''
+        })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(InheritanceTestCase))
+    suite.addTest(unittest.makeSuite(BugFixTestCase))
+    return suite


[54/59] [abbrv] git commit: AMBARI-7154. Configs: compare strangeness: content for yarn-log4j and yarn-env are the same.(XIWANG)

Posted by nc...@apache.org.
AMBARI-7154. Configs: compare strangeness: content for yarn-log4j and yarn-env are the same.(XIWANG)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fd732e3d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fd732e3d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fd732e3d

Branch: refs/heads/branch-alerts-dev
Commit: fd732e3d0f5346802a58a665b57a14d673c729a5
Parents: 3016782
Author: Xi Wang <xi...@apache.org>
Authored: Thu Sep 4 11:21:28 2014 -0700
Committer: Xi Wang <xi...@apache.org>
Committed: Thu Sep 4 13:00:08 2014 -0700

----------------------------------------------------------------------
 ambari-web/app/controllers/main/service/info/configs.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fd732e3d/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index 663fb36..346bc48 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -574,7 +574,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
         for (var prop in configuration.properties) {
           value += prop + '=' + configuration.properties[prop] + '\n';
         }
-        serviceVersionMap[configuration.type] = {
+        serviceVersionMap[configuration.type + '-' + configuration.type] = {
           name: configuration.type,
           value: value,
           type: configuration.type,
@@ -583,7 +583,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
         };
       } else {
         for (var prop in configuration.properties) {
-          serviceVersionMap[prop] = {
+          serviceVersionMap[prop + '-' + configuration.type] = {
             name: prop,
             value: configuration.properties[prop],
             type: configuration.type,
@@ -597,15 +597,15 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
       }
       if (configuration.properties_attributes && configuration.properties_attributes.final) {
         for (var final in configuration.properties_attributes.final) {
-          serviceVersionMap[final].isFinal = (configuration.properties_attributes.final[final] === 'true');
+          serviceVersionMap[final + '-' + configuration.type].isFinal = (configuration.properties_attributes.final[final] === 'true');
         }
       }
     }, this);
 
     allConfigs.forEach(function (serviceConfig) {
-      var compareConfig = serviceVersionMap[serviceConfig.name];
+      // map the property in the compare version to compare with current serviceConfig
+      var compareConfig = serviceVersionMap[serviceConfig.name + '-' + App.config.getConfigTagFromFileName(serviceConfig.filename)];
       var compareObject = $.extend(true, {isComparison: true}, serviceConfig);
-
       compareObject.serviceVersion = compareServiceVersion;
       compareObject.isEditable = false;
 


[31/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/sandbox.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/sandbox.py b/ambari-common/src/main/python/jinja2/jinja2/sandbox.py
deleted file mode 100644
index 7497195..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/sandbox.py
+++ /dev/null
@@ -1,271 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.sandbox
-    ~~~~~~~~~~~~~~
-
-    Adds a sandbox layer to Jinja as it was the default behavior in the old
-    Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
-    default behavior is easier to use.
-
-    The behavior can be changed by subclassing the environment.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD.
-"""
-import operator
-from jinja2.runtime import Undefined
-from jinja2.environment import Environment
-from jinja2.exceptions import SecurityError
-from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
-     FrameType, GeneratorType
-
-
-#: maximum number of items a range may produce
-MAX_RANGE = 100000
-
-#: attributes of function objects that are considered unsafe.
-UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
-                                  'func_defaults', 'func_globals'])
-
-#: unsafe method attributes.  function attributes are unsafe for methods too
-UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
-
-
-import warnings
-
-# make sure we don't warn in python 2.6 about stuff we don't care about
-warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
-                        module='jinja2.sandbox')
-
-from collections import deque
-
-_mutable_set_types = (set,)
-_mutable_mapping_types = (dict,)
-_mutable_sequence_types = (list,)
-
-
-# on python 2.x we can register the user collection types
-try:
-    from UserDict import UserDict, DictMixin
-    from UserList import UserList
-    _mutable_mapping_types += (UserDict, DictMixin)
-    _mutable_set_types += (UserList,)
-except ImportError:
-    pass
-
-# if sets is still available, register the mutable set from there as well
-try:
-    from sets import Set
-    _mutable_set_types += (Set,)
-except ImportError:
-    pass
-
-#: register Python 2.6 abstract base classes
-try:
-    from collections import MutableSet, MutableMapping, MutableSequence
-    _mutable_set_types += (MutableSet,)
-    _mutable_mapping_types += (MutableMapping,)
-    _mutable_sequence_types += (MutableSequence,)
-except ImportError:
-    pass
-
-_mutable_spec = (
-    (_mutable_set_types, frozenset([
-        'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
-        'symmetric_difference_update', 'update'
-    ])),
-    (_mutable_mapping_types, frozenset([
-        'clear', 'pop', 'popitem', 'setdefault', 'update'
-    ])),
-    (_mutable_sequence_types, frozenset([
-        'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
-    ])),
-    (deque, frozenset([
-        'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
-        'popleft', 'remove', 'rotate'
-    ]))
-)
-
-
-def safe_range(*args):
-    """A range that can't generate ranges with a length of more than
-    MAX_RANGE items.
-    """
-    rng = xrange(*args)
-    if len(rng) > MAX_RANGE:
-        raise OverflowError('range too big, maximum size for range is %d' %
-                            MAX_RANGE)
-    return rng
-
-
-def unsafe(f):
-    """
-    Mark a function or method as unsafe::
-
-        @unsafe
-        def delete(self):
-            pass
-    """
-    f.unsafe_callable = True
-    return f
-
-
-def is_internal_attribute(obj, attr):
-    """Test if the attribute given is an internal python attribute.  For
-    example this function returns `True` for the `func_code` attribute of
-    python objects.  This is useful if the environment method
-    :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
-
-    >>> from jinja2.sandbox import is_internal_attribute
-    >>> is_internal_attribute(lambda: None, "func_code")
-    True
-    >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
-    True
-    >>> is_internal_attribute(str, "upper")
-    False
-    """
-    if isinstance(obj, FunctionType):
-        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
-            return True
-    elif isinstance(obj, MethodType):
-        if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
-           attr in UNSAFE_METHOD_ATTRIBUTES:
-            return True
-    elif isinstance(obj, type):
-        if attr == 'mro':
-            return True
-    elif isinstance(obj, (CodeType, TracebackType, FrameType)):
-        return True
-    elif isinstance(obj, GeneratorType):
-        if attr == 'gi_frame':
-            return True
-    return attr.startswith('__')
-
-
-def modifies_known_mutable(obj, attr):
-    """This function checks if an attribute on a builtin mutable object
-    (list, dict, set or deque) would modify it if called.  It also supports
-    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
-    with Python 2.6 onwards the abstract base classes `MutableSet`,
-    `MutableMapping`, and `MutableSequence`.
-
-    >>> modifies_known_mutable({}, "clear")
-    True
-    >>> modifies_known_mutable({}, "keys")
-    False
-    >>> modifies_known_mutable([], "append")
-    True
-    >>> modifies_known_mutable([], "index")
-    False
-
-    If called with an unsupported object (such as unicode) `False` is
-    returned.
-
-    >>> modifies_known_mutable("foo", "upper")
-    False
-    """
-    for typespec, unsafe in _mutable_spec:
-        if isinstance(obj, typespec):
-            return attr in unsafe
-    return False
-
-
-class SandboxedEnvironment(Environment):
-    """The sandboxed environment.  It works like the regular environment but
-    tells the compiler to generate sandboxed code.  Additionally subclasses of
-    this environment may override the methods that tell the runtime what
-    attributes or functions are safe to access.
-
-    If the template tries to access insecure code a :exc:`SecurityError` is
-    raised.  However also other exceptions may occour during the rendering so
-    the caller has to ensure that all exceptions are catched.
-    """
-    sandboxed = True
-
-    def __init__(self, *args, **kwargs):
-        Environment.__init__(self, *args, **kwargs)
-        self.globals['range'] = safe_range
-
-    def is_safe_attribute(self, obj, attr, value):
-        """The sandboxed environment will call this method to check if the
-        attribute of an object is safe to access.  Per default all attributes
-        starting with an underscore are considered private as well as the
-        special attributes of internal python objects as returned by the
-        :func:`is_internal_attribute` function.
-        """
-        return not (attr.startswith('_') or is_internal_attribute(obj, attr))
-
-    def is_safe_callable(self, obj):
-        """Check if an object is safely callable.  Per default a function is
-        considered safe unless the `unsafe_callable` attribute exists and is
-        True.  Override this method to alter the behavior, but this won't
-        affect the `unsafe` decorator from this module.
-        """
-        return not (getattr(obj, 'unsafe_callable', False) or \
-                    getattr(obj, 'alters_data', False))
-
-    def getitem(self, obj, argument):
-        """Subscribe an object from sandboxed code."""
-        try:
-            return obj[argument]
-        except (TypeError, LookupError):
-            if isinstance(argument, basestring):
-                try:
-                    attr = str(argument)
-                except:
-                    pass
-                else:
-                    try:
-                        value = getattr(obj, attr)
-                    except AttributeError:
-                        pass
-                    else:
-                        if self.is_safe_attribute(obj, argument, value):
-                            return value
-                        return self.unsafe_undefined(obj, argument)
-        return self.undefined(obj=obj, name=argument)
-
-    def getattr(self, obj, attribute):
-        """Subscribe an object from sandboxed code and prefer the
-        attribute.  The attribute passed *must* be a bytestring.
-        """
-        try:
-            value = getattr(obj, attribute)
-        except AttributeError:
-            try:
-                return obj[attribute]
-            except (TypeError, LookupError):
-                pass
-        else:
-            if self.is_safe_attribute(obj, attribute, value):
-                return value
-            return self.unsafe_undefined(obj, attribute)
-        return self.undefined(obj=obj, name=attribute)
-
-    def unsafe_undefined(self, obj, attribute):
-        """Return an undefined object for unsafe attributes."""
-        return self.undefined('access to attribute %r of %r '
-                              'object is unsafe.' % (
-            attribute,
-            obj.__class__.__name__
-        ), name=attribute, obj=obj, exc=SecurityError)
-
-    def call(__self, __context, __obj, *args, **kwargs):
-        """Call an object from sandboxed code."""
-        # the double prefixes are to avoid double keyword argument
-        # errors when proxying the call.
-        if not __self.is_safe_callable(__obj):
-            raise SecurityError('%r is not safely callable' % (__obj,))
-        return __context.call(__obj, *args, **kwargs)
-
-
-class ImmutableSandboxedEnvironment(SandboxedEnvironment):
-    """Works exactly like the regular `SandboxedEnvironment` but does not
-    permit modifications on the builtin mutable objects `list`, `set`, and
-    `dict` by using the :func:`modifies_known_mutable` function.
-    """
-
-    def is_safe_attribute(self, obj, attr, value):
-        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
-            return False
-        return not modifies_known_mutable(obj, attr)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/tests.py b/ambari-common/src/main/python/jinja2/jinja2/tests.py
deleted file mode 100644
index d257eca..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/tests.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.tests
-    ~~~~~~~~~~~~
-
-    Jinja test functions. Used with the "is" operator.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-from jinja2.runtime import Undefined
-
-# nose, nothing here to test
-__test__ = False
-
-
-number_re = re.compile(r'^-?\d+(\.\d+)?$')
-regex_type = type(number_re)
-
-
-try:
-    test_callable = callable
-except NameError:
-    def test_callable(x):
-        return hasattr(x, '__call__')
-
-
-def test_odd(value):
-    """Return true if the variable is odd."""
-    return value % 2 == 1
-
-
-def test_even(value):
-    """Return true if the variable is even."""
-    return value % 2 == 0
-
-
-def test_divisibleby(value, num):
-    """Check if a variable is divisible by a number."""
-    return value % num == 0
-
-
-def test_defined(value):
-    """Return true if the variable is defined:
-
-    .. sourcecode:: jinja
-
-        {% if variable is defined %}
-            value of variable: {{ variable }}
-        {% else %}
-            variable is not defined
-        {% endif %}
-
-    See the :func:`default` filter for a simple way to set undefined
-    variables.
-    """
-    return not isinstance(value, Undefined)
-
-
-def test_undefined(value):
-    """Like :func:`defined` but the other way round."""
-    return isinstance(value, Undefined)
-
-
-def test_none(value):
-    """Return true if the variable is none."""
-    return value is None
-
-
-def test_lower(value):
-    """Return true if the variable is lowercased."""
-    return unicode(value).islower()
-
-
-def test_upper(value):
-    """Return true if the variable is uppercased."""
-    return unicode(value).isupper()
-
-
-def test_string(value):
-    """Return true if the object is a string."""
-    return isinstance(value, basestring)
-
-
-def test_number(value):
-    """Return true if the variable is a number."""
-    return isinstance(value, (int, long, float, complex))
-
-
-def test_sequence(value):
-    """Return true if the variable is a sequence. Sequences are variables
-    that are iterable.
-    """
-    try:
-        len(value)
-        value.__getitem__
-    except:
-        return False
-    return True
-
-
-def test_sameas(value, other):
-    """Check if an object points to the same memory address than another
-    object:
-
-    .. sourcecode:: jinja
-
-        {% if foo.attribute is sameas false %}
-            the foo attribute really is the `False` singleton
-        {% endif %}
-    """
-    return value is other
-
-
-def test_iterable(value):
-    """Check if it's possible to iterate over an object."""
-    try:
-        iter(value)
-    except TypeError:
-        return False
-    return True
-
-
-def test_escaped(value):
-    """Check if the value is escaped."""
-    return hasattr(value, '__html__')
-
-
-TESTS = {
-    'odd':              test_odd,
-    'even':             test_even,
-    'divisibleby':      test_divisibleby,
-    'defined':          test_defined,
-    'undefined':        test_undefined,
-    'none':             test_none,
-    'lower':            test_lower,
-    'upper':            test_upper,
-    'string':           test_string,
-    'number':           test_number,
-    'sequence':         test_sequence,
-    'iterable':         test_iterable,
-    'callable':         test_callable,
-    'sameas':           test_sameas,
-    'escaped':          test_escaped
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py
deleted file mode 100644
index 1f10ef6..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite
-    ~~~~~~~~~~~~~~~~
-
-    All the unittests of Jinja2.  These tests can be executed by
-    either running run-tests.py using multiple Python versions at
-    the same time.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import re
-import sys
-import unittest
-from traceback import format_exception
-from jinja2 import loaders
-
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-dict_loader = loaders.DictLoader({
-    'justdict.html':        'FOO'
-})
-package_loader = loaders.PackageLoader('jinja2.testsuite.res', 'templates')
-filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
-function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
-choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
-prefix_loader = loaders.PrefixLoader({
-    'a':        filesystem_loader,
-    'b':        dict_loader
-})
-
-
-class JinjaTestCase(unittest.TestCase):
-
-    ### use only these methods for testing.  If you need standard
-    ### unittest method, wrap them!
-
-    def setup(self):
-        pass
-
-    def teardown(self):
-        pass
-
-    def setUp(self):
-        self.setup()
-
-    def tearDown(self):
-        self.teardown()
-
-    def assert_equal(self, a, b):
-        return self.assertEqual(a, b)
-
-    def assert_raises(self, *args, **kwargs):
-        return self.assertRaises(*args, **kwargs)
-
-    def assert_traceback_matches(self, callback, expected_tb):
-        try:
-            callback()
-        except Exception, e:
-            tb = format_exception(*sys.exc_info())
-            if re.search(expected_tb.strip(), ''.join(tb)) is None:
-                raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
-                    % (''.join(tb), expected_tb))
-        else:
-            self.fail('Expected exception')
-
-
-def suite():
-    from jinja2.testsuite import ext, filters, tests, core_tags, \
-         loader, inheritance, imports, lexnparse, security, api, \
-         regression, debug, utils, doctests
-    suite = unittest.TestSuite()
-    suite.addTest(ext.suite())
-    suite.addTest(filters.suite())
-    suite.addTest(tests.suite())
-    suite.addTest(core_tags.suite())
-    suite.addTest(loader.suite())
-    suite.addTest(inheritance.suite())
-    suite.addTest(imports.suite())
-    suite.addTest(lexnparse.suite())
-    suite.addTest(security.suite())
-    suite.addTest(api.suite())
-    suite.addTest(regression.suite())
-    suite.addTest(debug.suite())
-    suite.addTest(utils.suite())
-
-    # doctests will not run on python 3 currently.  Too many issues
-    # with that, do not test that on that platform.
-    if sys.version_info < (3, 0):
-        suite.addTest(doctests.suite())
-
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py
deleted file mode 100644
index 7463c7f..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py
+++ /dev/null
@@ -1,240 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.api
-    ~~~~~~~~~~~~~~~~~~~~
-
-    Tests the public API and related stuff.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment, Undefined, DebugUndefined, \
-     StrictUndefined, UndefinedError, Template, meta, \
-     is_undefined, Template, DictLoader
-from jinja2.utils import Cycler
-
-env = Environment()
-
-
-class ExtendedAPITestCase(JinjaTestCase):
-
-    def test_item_and_attribute(self):
-        from jinja2.sandbox import SandboxedEnvironment
-
-        for env in Environment(), SandboxedEnvironment():
-            # the |list is necessary for python3
-            tmpl = env.from_string('{{ foo.items()|list }}')
-            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
-            tmpl = env.from_string('{{ foo|attr("items")()|list }}')
-            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
-            tmpl = env.from_string('{{ foo["items"] }}')
-            assert tmpl.render(foo={'items': 42}) == '42'
-
-    def test_finalizer(self):
-        def finalize_none_empty(value):
-            if value is None:
-                value = u''
-            return value
-        env = Environment(finalize=finalize_none_empty)
-        tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
-        assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo'
-        tmpl = env.from_string('<{{ none }}>')
-        assert tmpl.render() == '<>'
-
-    def test_cycler(self):
-        items = 1, 2, 3
-        c = Cycler(*items)
-        for item in items + items:
-            assert c.current == item
-            assert c.next() == item
-        c.next()
-        assert c.current == 2
-        c.reset()
-        assert c.current == 1
-
-    def test_expressions(self):
-        expr = env.compile_expression("foo")
-        assert expr() is None
-        assert expr(foo=42) == 42
-        expr2 = env.compile_expression("foo", undefined_to_none=False)
-        assert is_undefined(expr2())
-
-        expr = env.compile_expression("42 + foo")
-        assert expr(foo=42) == 84
-
-    def test_template_passthrough(self):
-        t = Template('Content')
-        assert env.get_template(t) is t
-        assert env.select_template([t]) is t
-        assert env.get_or_select_template([t]) is t
-        assert env.get_or_select_template(t) is t
-
-    def test_autoescape_autoselect(self):
-        def select_autoescape(name):
-            if name is None or '.' not in name:
-                return False
-            return name.endswith('.html')
-        env = Environment(autoescape=select_autoescape,
-                          loader=DictLoader({
-            'test.txt':     '{{ foo }}',
-            'test.html':    '{{ foo }}'
-        }))
-        t = env.get_template('test.txt')
-        assert t.render(foo='<foo>') == '<foo>'
-        t = env.get_template('test.html')
-        assert t.render(foo='<foo>') == '&lt;foo&gt;'
-        t = env.from_string('{{ foo }}')
-        assert t.render(foo='<foo>') == '<foo>'
-
-
-class MetaTestCase(JinjaTestCase):
-
-    def test_find_undeclared_variables(self):
-        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
-        x = meta.find_undeclared_variables(ast)
-        assert x == set(['bar'])
-
-        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
-                        '{% macro meh(x) %}{{ x }}{% endmacro %}'
-                        '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
-        x = meta.find_undeclared_variables(ast)
-        assert x == set(['bar', 'seq', 'muh'])
-
-    def test_find_refererenced_templates(self):
-        ast = env.parse('{% extends "layout.html" %}{% include helper %}')
-        i = meta.find_referenced_templates(ast)
-        assert i.next() == 'layout.html'
-        assert i.next() is None
-        assert list(i) == []
-
-        ast = env.parse('{% extends "layout.html" %}'
-                        '{% from "test.html" import a, b as c %}'
-                        '{% import "meh.html" as meh %}'
-                        '{% include "muh.html" %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
-
-    def test_find_included_templates(self):
-        ast = env.parse('{% include ["foo.html", "bar.html"] %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html']
-
-        ast = env.parse('{% include ("foo.html", "bar.html") %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html']
-
-        ast = env.parse('{% include ["foo.html", "bar.html", foo] %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html', None]
-
-        ast = env.parse('{% include ("foo.html", "bar.html", foo) %}')
-        i = meta.find_referenced_templates(ast)
-        assert list(i) == ['foo.html', 'bar.html', None]
-
-
-class StreamingTestCase(JinjaTestCase):
-
-    def test_basic_streaming(self):
-        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
-                               "}} - {{ item }}</li>{%- endfor %}</ul>")
-        stream = tmpl.stream(seq=range(4))
-        self.assert_equal(stream.next(), '<ul>')
-        self.assert_equal(stream.next(), '<li>1 - 0</li>')
-        self.assert_equal(stream.next(), '<li>2 - 1</li>')
-        self.assert_equal(stream.next(), '<li>3 - 2</li>')
-        self.assert_equal(stream.next(), '<li>4 - 3</li>')
-        self.assert_equal(stream.next(), '</ul>')
-
-    def test_buffered_streaming(self):
-        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
-                               "}} - {{ item }}</li>{%- endfor %}</ul>")
-        stream = tmpl.stream(seq=range(4))
-        stream.enable_buffering(size=3)
-        self.assert_equal(stream.next(), u'<ul><li>1 - 0</li><li>2 - 1</li>')
-        self.assert_equal(stream.next(), u'<li>3 - 2</li><li>4 - 3</li></ul>')
-
-    def test_streaming_behavior(self):
-        tmpl = env.from_string("")
-        stream = tmpl.stream()
-        assert not stream.buffered
-        stream.enable_buffering(20)
-        assert stream.buffered
-        stream.disable_buffering()
-        assert not stream.buffered
-
-
-class UndefinedTestCase(JinjaTestCase):
-
-    def test_stopiteration_is_undefined(self):
-        def test():
-            raise StopIteration()
-        t = Template('A{{ test() }}B')
-        assert t.render(test=test) == 'AB'
-        t = Template('A{{ test().missingattribute }}B')
-        self.assert_raises(UndefinedError, t.render, test=test)
-
-    def test_default_undefined(self):
-        env = Environment(undefined=Undefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), u'')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
-    def test_debug_undefined(self):
-        env = Environment(undefined=DebugUndefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
-                          u"{{ no such element: int object['missing'] }}")
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
-    def test_strict_undefined(self):
-        env = Environment(undefined=StrictUndefined)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
-        self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
-
-    def test_indexing_gives_undefined(self):
-        t = Template("{{ var[42].foo }}")
-        self.assert_raises(UndefinedError, t.render, var=0)
-
-    def test_none_gives_proper_error(self):
-        try:
-            Environment().getattr(None, 'split')()
-        except UndefinedError, e:
-            assert e.message == "'None' has no attribute 'split'"
-        else:
-            assert False, 'expected exception'
-
-    def test_object_repr(self):
-        try:
-            Undefined(obj=42, name='upper')()
-        except UndefinedError, e:
-            assert e.message == "'int object' has no attribute 'upper'"
-        else:
-            assert False, 'expected exception'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
-    suite.addTest(unittest.makeSuite(MetaTestCase))
-    suite.addTest(unittest.makeSuite(StreamingTestCase))
-    suite.addTest(unittest.makeSuite(UndefinedTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py
deleted file mode 100644
index d456b4f..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py
+++ /dev/null
@@ -1,286 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.core_tags
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Test the core tags like for and if.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
-     DictLoader
-
-env = Environment()
-
-
-class ForLoopTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
-        assert tmpl.render(seq=range(10)) == '0123456789'
-
-    def test_else(self):
-        tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
-        assert tmpl.render() == '...'
-
-    def test_empty_blocks(self):
-        tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
-        assert tmpl.render() == '<>'
-
-    def test_context_vars(self):
-        tmpl = env.from_string('''{% for item in seq -%}
-        {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
-            loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
-           loop.length }}###{% endfor %}''')
-        one, two, _ = tmpl.render(seq=[0, 1]).split('###')
-        (one_index, one_index0, one_revindex, one_revindex0, one_first,
-         one_last, one_length) = one.split('|')
-        (two_index, two_index0, two_revindex, two_revindex0, two_first,
-         two_last, two_length) = two.split('|')
-
-        assert int(one_index) == 1 and int(two_index) == 2
-        assert int(one_index0) == 0 and int(two_index0) == 1
-        assert int(one_revindex) == 2 and int(two_revindex) == 1
-        assert int(one_revindex0) == 1 and int(two_revindex0) == 0
-        assert one_first == 'True' and two_first == 'False'
-        assert one_last == 'False' and two_last == 'True'
-        assert one_length == two_length == '2'
-
-    def test_cycling(self):
-        tmpl = env.from_string('''{% for item in seq %}{{
-            loop.cycle('<1>', '<2>') }}{% endfor %}{%
-            for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
-        output = tmpl.render(seq=range(4), through=('<1>', '<2>'))
-        assert output == '<1><2>' * 4
-
-    def test_scope(self):
-        tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
-        output = tmpl.render(seq=range(10))
-        assert not output
-
-    def test_varlen(self):
-        def inner():
-            for item in range(5):
-                yield item
-        tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}')
-        output = tmpl.render(iter=inner())
-        assert output == '01234'
-
-    def test_noniter(self):
-        tmpl = env.from_string('{% for item in none %}...{% endfor %}')
-        self.assert_raises(TypeError, tmpl.render)
-
-    def test_recursive(self):
-        tmpl = env.from_string('''{% for item in seq recursive -%}
-            [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
-        {%- endfor %}''')
-        assert tmpl.render(seq=[
-            dict(a=1, b=[dict(a=1), dict(a=2)]),
-            dict(a=2, b=[dict(a=1), dict(a=2)]),
-            dict(a=3, b=[dict(a='a')])
-        ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
-
-    def test_looploop(self):
-        tmpl = env.from_string('''{% for row in table %}
-            {%- set rowloop = loop -%}
-            {% for cell in row -%}
-                [{{ rowloop.index }}|{{ loop.index }}]
-            {%- endfor %}
-        {%- endfor %}''')
-        assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
-
-    def test_reversed_bug(self):
-        tmpl = env.from_string('{% for i in items %}{{ i }}'
-                               '{% if not loop.last %}'
-                               ',{% endif %}{% endfor %}')
-        assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
-
-    def test_loop_errors(self):
-        tmpl = env.from_string('''{% for item in [1] if loop.index
-                                      == 0 %}...{% endfor %}''')
-        self.assert_raises(UndefinedError, tmpl.render)
-        tmpl = env.from_string('''{% for item in [] %}...{% else
-            %}{{ loop }}{% endfor %}''')
-        assert tmpl.render() == ''
-
-    def test_loop_filter(self):
-        tmpl = env.from_string('{% for item in range(10) if item '
-                               'is even %}[{{ item }}]{% endfor %}')
-        assert tmpl.render() == '[0][2][4][6][8]'
-        tmpl = env.from_string('''
-            {%- for item in range(10) if item is even %}[{{
-                loop.index }}:{{ item }}]{% endfor %}''')
-        assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
-
-    def test_loop_unassignable(self):
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{% for loop in seq %}...{% endfor %}')
-
-    def test_scoped_special_var(self):
-        t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
-                            '|{{ loop.first }}{% endfor %}]{% endfor %}')
-        assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
-
-    def test_scoped_loop_var(self):
-        t = env.from_string('{% for x in seq %}{{ loop.first }}'
-                            '{% for y in seq %}{% endfor %}{% endfor %}')
-        assert t.render(seq='ab') == 'TrueFalse'
-        t = env.from_string('{% for x in seq %}{% for y in seq %}'
-                            '{{ loop.first }}{% endfor %}{% endfor %}')
-        assert t.render(seq='ab') == 'TrueFalseTrueFalse'
-
-    def test_recursive_empty_loop_iter(self):
-        t = env.from_string('''
-        {%- for item in foo recursive -%}{%- endfor -%}
-        ''')
-        assert t.render(dict(foo=[])) == ''
-
-    def test_call_in_loop(self):
-        t = env.from_string('''
-        {%- macro do_something() -%}
-            [{{ caller() }}]
-        {%- endmacro %}
-
-        {%- for i in [1, 2, 3] %}
-            {%- call do_something() -%}
-                {{ i }}
-            {%- endcall %}
-        {%- endfor -%}
-        ''')
-        assert t.render() == '[1][2][3]'
-
-    def test_scoping_bug(self):
-        t = env.from_string('''
-        {%- for item in foo %}...{{ item }}...{% endfor %}
-        {%- macro item(a) %}...{{ a }}...{% endmacro %}
-        {{- item(2) -}}
-        ''')
-        assert t.render(foo=(1,)) == '...1......2...'
-
-    def test_unpacking(self):
-        tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
-            '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
-        assert tmpl.render() == '1|2|3'
-
-
-class IfConditionTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        tmpl = env.from_string('''{% if true %}...{% endif %}''')
-        assert tmpl.render() == '...'
-
-    def test_elif(self):
-        tmpl = env.from_string('''{% if false %}XXX{% elif true
-            %}...{% else %}XXX{% endif %}''')
-        assert tmpl.render() == '...'
-
-    def test_else(self):
-        tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
-        assert tmpl.render() == '...'
-
-    def test_empty(self):
-        tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
-        assert tmpl.render() == '[]'
-
-    def test_complete(self):
-        tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
-                               'C{% else %}D{% endif %}')
-        assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
-
-    def test_no_scope(self):
-        tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
-        assert tmpl.render(a=True) == '1'
-        tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
-        assert tmpl.render() == '1'
-
-
-class MacrosTestCase(JinjaTestCase):
-    env = Environment(trim_blocks=True)
-
-    def test_simple(self):
-        tmpl = self.env.from_string('''\
-{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
-{{ say_hello('Peter') }}''')
-        assert tmpl.render() == 'Hello Peter!'
-
-    def test_scoping(self):
-        tmpl = self.env.from_string('''\
-{% macro level1(data1) %}
-{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
-{{ level2('bar') }}{% endmacro %}
-{{ level1('foo') }}''')
-        assert tmpl.render() == 'foo|bar'
-
-    def test_arguments(self):
-        tmpl = self.env.from_string('''\
-{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
-{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
-        assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
-
-    def test_varargs(self):
-        tmpl = self.env.from_string('''\
-{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
-{{ test(1, 2, 3) }}''')
-        assert tmpl.render() == '1|2|3'
-
-    def test_simple_call(self):
-        tmpl = self.env.from_string('''\
-{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
-{% call test() %}data{% endcall %}''')
-        assert tmpl.render() == '[[data]]'
-
-    def test_complex_call(self):
-        tmpl = self.env.from_string('''\
-{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
-{% call(data) test() %}{{ data }}{% endcall %}''')
-        assert tmpl.render() == '[[data]]'
-
-    def test_caller_undefined(self):
-        tmpl = self.env.from_string('''\
-{% set caller = 42 %}\
-{% macro test() %}{{ caller is not defined }}{% endmacro %}\
-{{ test() }}''')
-        assert tmpl.render() == 'True'
-
-    def test_include(self):
-        self.env = Environment(loader=DictLoader({'include':
-            '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
-        tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
-        assert tmpl.render() == '[foo]'
-
-    def test_macro_api(self):
-        tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
-                               '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
-                               '{% macro baz() %}{{ caller() }}{% endmacro %}')
-        assert tmpl.module.foo.arguments == ('a', 'b')
-        assert tmpl.module.foo.defaults == ()
-        assert tmpl.module.foo.name == 'foo'
-        assert not tmpl.module.foo.caller
-        assert not tmpl.module.foo.catch_kwargs
-        assert not tmpl.module.foo.catch_varargs
-        assert tmpl.module.bar.arguments == ()
-        assert tmpl.module.bar.defaults == ()
-        assert not tmpl.module.bar.caller
-        assert tmpl.module.bar.catch_kwargs
-        assert tmpl.module.bar.catch_varargs
-        assert tmpl.module.baz.caller
-
-    def test_callself(self):
-        tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
-                                    '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
-                                    '{{ foo(5) }}')
-        assert tmpl.render() == '5|4|3|2|1'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ForLoopTestCase))
-    suite.addTest(unittest.makeSuite(IfConditionTestCase))
-    suite.addTest(unittest.makeSuite(MacrosTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py
deleted file mode 100644
index 7552dec..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.debug
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests the debug system.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import sys
-import unittest
-
-from jinja2.testsuite import JinjaTestCase, filesystem_loader
-
-from jinja2 import Environment, TemplateSyntaxError
-
-env = Environment(loader=filesystem_loader)
-
-
-class DebugTestCase(JinjaTestCase):
-
-    if sys.version_info[:2] != (2, 4):
-        def test_runtime_error(self):
-            def test():
-                tmpl.render(fail=lambda: 1 / 0)
-            tmpl = env.get_template('broken.html')
-            self.assert_traceback_matches(test, r'''
-  File ".*?broken.html", line 2, in (top-level template code|<module>)
-    \{\{ fail\(\) \}\}
-  File ".*?debug.pyc?", line \d+, in <lambda>
-    tmpl\.render\(fail=lambda: 1 / 0\)
-ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
-''')
-
-    def test_syntax_error(self):
-        # XXX: the .*? is necessary for python3 which does not hide
-        # some of the stack frames we don't want to show.  Not sure
-        # what's up with that, but that is not that critical.  Should
-        # be fixed though.
-        self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
-  File ".*?syntaxerror.html", line 4, in (template|<module>)
-    \{% endif %\}.*?
-(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
-    ''')
-
-    def test_regular_syntax_error(self):
-        def test():
-            raise TemplateSyntaxError('wtf', 42)
-        self.assert_traceback_matches(test, r'''
-  File ".*debug.pyc?", line \d+, in test
-    raise TemplateSyntaxError\('wtf', 42\)
-(jinja2\.exceptions\.)?TemplateSyntaxError: wtf
-  line 42''')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(DebugTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py
deleted file mode 100644
index 616d3b6..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.doctests
-    ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    The doctests.  Collects all tests we want to test from
-    the Jinja modules.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-import doctest
-
-
-def suite():
-    from jinja2 import utils, sandbox, runtime, meta, loaders, \
-        ext, environment, bccache, nodes
-    suite = unittest.TestSuite()
-    suite.addTest(doctest.DocTestSuite(utils))
-    suite.addTest(doctest.DocTestSuite(sandbox))
-    suite.addTest(doctest.DocTestSuite(runtime))
-    suite.addTest(doctest.DocTestSuite(meta))
-    suite.addTest(doctest.DocTestSuite(loaders))
-    suite.addTest(doctest.DocTestSuite(ext))
-    suite.addTest(doctest.DocTestSuite(environment))
-    suite.addTest(doctest.DocTestSuite(bccache))
-    suite.addTest(doctest.DocTestSuite(nodes))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py
deleted file mode 100644
index 89b8579..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py
+++ /dev/null
@@ -1,455 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.ext
-    ~~~~~~~~~~~~~~~~~~~~
-
-    Tests for the extensions.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import re
-import unittest
-
-from jinja2.testsuite import JinjaTestCase, filesystem_loader
-
-from jinja2 import Environment, DictLoader, contextfunction, nodes
-from jinja2.exceptions import TemplateAssertionError
-from jinja2.ext import Extension
-from jinja2.lexer import Token, count_newlines
-from jinja2.utils import next
-
-# 2.x / 3.x
-try:
-    from io import BytesIO
-except ImportError:
-    from StringIO import StringIO as BytesIO
-
-
-importable_object = 23
-
-_gettext_re = re.compile(r'_\((.*?)\)(?s)')
-
-
-i18n_templates = {
-    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
-                   '{% block body %}{% endblock %}',
-    'child.html': '{% extends "master.html" %}{% block body %}'
-                  '{% trans %}watch out{% endtrans %}{% endblock %}',
-    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
-                   '{{ user_count }} users online{% endtrans %}',
-    'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}'
-}
-
-newstyle_i18n_templates = {
-    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
-                   '{% block body %}{% endblock %}',
-    'child.html': '{% extends "master.html" %}{% block body %}'
-                  '{% trans %}watch out{% endtrans %}{% endblock %}',
-    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
-                   '{{ user_count }} users online{% endtrans %}',
-    'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}',
-    'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}',
-    'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}'
-                          '{{ num }} apples{% endtrans %}',
-    'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}',
-    'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}',
-    'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}',
-    'novars.html': '{% trans %}%(hello)s{% endtrans %}',
-    'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}',
-    'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}'
-}
-
-
-languages = {
-    'de': {
-        'missing':                      u'fehlend',
-        'watch out':                    u'pass auf',
-        'One user online':              u'Ein Benutzer online',
-        '%(user_count)s users online':  u'%(user_count)s Benutzer online',
-        'User: %(num)s':                u'Benutzer: %(num)s',
-        'User: %(count)s':              u'Benutzer: %(count)s',
-        '%(num)s apple':                u'%(num)s Apfel',
-        '%(num)s apples':               u'%(num)s Äpfel'
-    }
-}
-
-
-@contextfunction
-def gettext(context, string):
-    language = context.get('LANGUAGE', 'en')
-    return languages.get(language, {}).get(string, string)
-
-
-@contextfunction
-def ngettext(context, s, p, n):
-    language = context.get('LANGUAGE', 'en')
-    if n != 1:
-        return languages.get(language, {}).get(p, p)
-    return languages.get(language, {}).get(s, s)
-
-
-i18n_env = Environment(
-    loader=DictLoader(i18n_templates),
-    extensions=['jinja2.ext.i18n']
-)
-i18n_env.globals.update({
-    '_':            gettext,
-    'gettext':      gettext,
-    'ngettext':     ngettext
-})
-
-newstyle_i18n_env = Environment(
-    loader=DictLoader(newstyle_i18n_templates),
-    extensions=['jinja2.ext.i18n']
-)
-newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
-
-class TestExtension(Extension):
-    tags = set(['test'])
-    ext_attr = 42
-
-    def parse(self, parser):
-        return nodes.Output([self.call_method('_dump', [
-            nodes.EnvironmentAttribute('sandboxed'),
-            self.attr('ext_attr'),
-            nodes.ImportedName(__name__ + '.importable_object'),
-            nodes.ContextReference()
-        ])]).set_lineno(next(parser.stream).lineno)
-
-    def _dump(self, sandboxed, ext_attr, imported_object, context):
-        return '%s|%s|%s|%s' % (
-            sandboxed,
-            ext_attr,
-            imported_object,
-            context.blocks
-        )
-
-
-class PreprocessorExtension(Extension):
-
-    def preprocess(self, source, name, filename=None):
-        return source.replace('[[TEST]]', '({{ foo }})')
-
-
-class StreamFilterExtension(Extension):
-
-    def filter_stream(self, stream):
-        for token in stream:
-            if token.type == 'data':
-                for t in self.interpolate(token):
-                    yield t
-            else:
-                yield token
-
-    def interpolate(self, token):
-        pos = 0
-        end = len(token.value)
-        lineno = token.lineno
-        while 1:
-            match = _gettext_re.search(token.value, pos)
-            if match is None:
-                break
-            value = token.value[pos:match.start()]
-            if value:
-                yield Token(lineno, 'data', value)
-            lineno += count_newlines(token.value)
-            yield Token(lineno, 'variable_begin', None)
-            yield Token(lineno, 'name', 'gettext')
-            yield Token(lineno, 'lparen', None)
-            yield Token(lineno, 'string', match.group(1))
-            yield Token(lineno, 'rparen', None)
-            yield Token(lineno, 'variable_end', None)
-            pos = match.end()
-        if pos < end:
-            yield Token(lineno, 'data', token.value[pos:])
-
-
-class ExtensionsTestCase(JinjaTestCase):
-
-    def test_extend_late(self):
-        env = Environment()
-        env.add_extension('jinja2.ext.autoescape')
-        t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
-        assert t.render() == '&lt;test&gt;'
-
-    def test_loop_controls(self):
-        env = Environment(extensions=['jinja2.ext.loopcontrols'])
-
-        tmpl = env.from_string('''
-            {%- for item in [1, 2, 3, 4] %}
-                {%- if item % 2 == 0 %}{% continue %}{% endif -%}
-                {{ item }}
-            {%- endfor %}''')
-        assert tmpl.render() == '13'
-
-        tmpl = env.from_string('''
-            {%- for item in [1, 2, 3, 4] %}
-                {%- if item > 2 %}{% break %}{% endif -%}
-                {{ item }}
-            {%- endfor %}''')
-        assert tmpl.render() == '12'
-
-    def test_do(self):
-        env = Environment(extensions=['jinja2.ext.do'])
-        tmpl = env.from_string('''
-            {%- set items = [] %}
-            {%- for char in "foo" %}
-                {%- do items.append(loop.index0 ~ char) %}
-            {%- endfor %}{{ items|join(', ') }}''')
-        assert tmpl.render() == '0f, 1o, 2o'
-
-    def test_with(self):
-        env = Environment(extensions=['jinja2.ext.with_'])
-        tmpl = env.from_string('''\
-        {% with a=42, b=23 -%}
-            {{ a }} = {{ b }}
-        {% endwith -%}
-            {{ a }} = {{ b }}\
-        ''')
-        assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
-            == ['42 = 23', '1 = 2']
-
-    def test_extension_nodes(self):
-        env = Environment(extensions=[TestExtension])
-        tmpl = env.from_string('{% test %}')
-        assert tmpl.render() == 'False|42|23|{}'
-
-    def test_identifier(self):
-        assert TestExtension.identifier == __name__ + '.TestExtension'
-
-    def test_rebinding(self):
-        original = Environment(extensions=[TestExtension])
-        overlay = original.overlay()
-        for env in original, overlay:
-            for ext in env.extensions.itervalues():
-                assert ext.environment is env
-
-    def test_preprocessor_extension(self):
-        env = Environment(extensions=[PreprocessorExtension])
-        tmpl = env.from_string('{[[TEST]]}')
-        assert tmpl.render(foo=42) == '{(42)}'
-
-    def test_streamfilter_extension(self):
-        env = Environment(extensions=[StreamFilterExtension])
-        env.globals['gettext'] = lambda x: x.upper()
-        tmpl = env.from_string('Foo _(bar) Baz')
-        out = tmpl.render()
-        assert out == 'Foo BAR Baz'
-
-    def test_extension_ordering(self):
-        class T1(Extension):
-            priority = 1
-        class T2(Extension):
-            priority = 2
-        env = Environment(extensions=[T1, T2])
-        ext = list(env.iter_extensions())
-        assert ext[0].__class__ is T1
-        assert ext[1].__class__ is T2
-
-
-class InternationalizationTestCase(JinjaTestCase):
-
-    def test_trans(self):
-        tmpl = i18n_env.get_template('child.html')
-        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
-
-    def test_trans_plural(self):
-        tmpl = i18n_env.get_template('plural.html')
-        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
-        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
-
-    def test_complex_plural(self):
-        tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
-                                    'pluralize count %}{{ count }} items{% endtrans %}')
-        assert tmpl.render() == '2 items'
-        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
-                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
-
-    def test_trans_stringformatting(self):
-        tmpl = i18n_env.get_template('stringformat.html')
-        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
-
-    def test_extract(self):
-        from jinja2.ext import babel_extract
-        source = BytesIO('''
-        {{ gettext('Hello World') }}
-        {% trans %}Hello World{% endtrans %}
-        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        '''.encode('ascii')) # make python 3 happy
-        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
-            (2, 'gettext', u'Hello World', []),
-            (3, 'gettext', u'Hello World', []),
-            (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
-        ]
-
-    def test_comment_extract(self):
-        from jinja2.ext import babel_extract
-        source = BytesIO('''
-        {# trans first #}
-        {{ gettext('Hello World') }}
-        {% trans %}Hello World{% endtrans %}{# trans second #}
-        {#: third #}
-        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        '''.encode('utf-8')) # make python 3 happy
-        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
-            (3, 'gettext', u'Hello World', ['first']),
-            (4, 'gettext', u'Hello World', ['second']),
-            (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
-        ]
-
-
-class NewstyleInternationalizationTestCase(JinjaTestCase):
-
-    def test_trans(self):
-        tmpl = newstyle_i18n_env.get_template('child.html')
-        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
-
-    def test_trans_plural(self):
-        tmpl = newstyle_i18n_env.get_template('plural.html')
-        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
-        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
-
-    def test_complex_plural(self):
-        tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
-                                    'pluralize count %}{{ count }} items{% endtrans %}')
-        assert tmpl.render() == '2 items'
-        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
-                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
-
-    def test_trans_stringformatting(self):
-        tmpl = newstyle_i18n_env.get_template('stringformat.html')
-        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
-
-    def test_newstyle_plural(self):
-        tmpl = newstyle_i18n_env.get_template('ngettext.html')
-        assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel'
-        assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel'
-
-    def test_autoescape_support(self):
-        env = Environment(extensions=['jinja2.ext.autoescape',
-                                      'jinja2.ext.i18n'])
-        env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
-                                      lambda s, p, n: s, newstyle=True)
-        t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
-                            '"<test>") }}{% endautoescape %}')
-        assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
-        assert t.render(ae=False) == '<strong>Wert: <test></strong>'
-
-    def test_num_used_twice(self):
-        tmpl = newstyle_i18n_env.get_template('ngettext_long.html')
-        assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Äpfel'
-
-    def test_num_called_num(self):
-        source = newstyle_i18n_env.compile('''
-            {% trans num=3 %}{{ num }} apple{% pluralize
-            %}{{ num }} apples{% endtrans %}
-        ''', raw=True)
-        # quite hacky, but the only way to properly test that.  The idea is
-        # that the generated code does not pass num twice (although that
-        # would work) for better performance.  This only works on the
-        # newstyle gettext of course
-        assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s "
-                         r"apples', 3", source) is not None
-
-    def test_trans_vars(self):
-        t1 = newstyle_i18n_env.get_template('transvars1.html')
-        t2 = newstyle_i18n_env.get_template('transvars2.html')
-        t3 = newstyle_i18n_env.get_template('transvars3.html')
-        assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1'
-        assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23'
-        assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42'
-
-    def test_novars_vars_escaping(self):
-        t = newstyle_i18n_env.get_template('novars.html')
-        assert t.render() == '%(hello)s'
-        t = newstyle_i18n_env.get_template('vars.html')
-        assert t.render(foo='42') == '42%(foo)s'
-        t = newstyle_i18n_env.get_template('explicitvars.html')
-        assert t.render() == '%(foo)s'
-
-
-class AutoEscapeTestCase(JinjaTestCase):
-
-    def test_scoped_setting(self):
-        env = Environment(extensions=['jinja2.ext.autoescape'],
-                          autoescape=True)
-        tmpl = env.from_string('''
-            {{ "<HelloWorld>" }}
-            {% autoescape false %}
-                {{ "<HelloWorld>" }}
-            {% endautoescape %}
-            {{ "<HelloWorld>" }}
-        ''')
-        assert tmpl.render().split() == \
-            [u'&lt;HelloWorld&gt;', u'<HelloWorld>', u'&lt;HelloWorld&gt;']
-
-        env = Environment(extensions=['jinja2.ext.autoescape'],
-                          autoescape=False)
-        tmpl = env.from_string('''
-            {{ "<HelloWorld>" }}
-            {% autoescape true %}
-                {{ "<HelloWorld>" }}
-            {% endautoescape %}
-            {{ "<HelloWorld>" }}
-        ''')
-        assert tmpl.render().split() == \
-            [u'<HelloWorld>', u'&lt;HelloWorld&gt;', u'<HelloWorld>']
-
-    def test_nonvolatile(self):
-        env = Environment(extensions=['jinja2.ext.autoescape'],
-                          autoescape=True)
-        tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}')
-        assert tmpl.render() == ' foo="&lt;test&gt;"'
-        tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}'
-                               '|xmlattr|escape }}{% endautoescape %}')
-        assert tmpl.render() == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
-
-    def test_volatile(self):
-        env = Environment(extensions=['jinja2.ext.autoescape'],
-                          autoescape=True)
-        tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}'
-                               '|xmlattr|escape }}{% endautoescape %}')
-        assert tmpl.render(foo=False) == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
-        assert tmpl.render(foo=True) == ' foo="&lt;test&gt;"'
-
-    def test_scoping(self):
-        env = Environment(extensions=['jinja2.ext.autoescape'])
-        tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
-                               '{% endautoescape %}{{ x }}{{ "<y>" }}')
-        assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
-
-    def test_volatile_scoping(self):
-        env = Environment(extensions=['jinja2.ext.autoescape'])
-        tmplsource = '''
-        {% autoescape val %}
-            {% macro foo(x) %}
-                [{{ x }}]
-            {% endmacro %}
-            {{ foo().__class__.__name__ }}
-        {% endautoescape %}
-        {{ '<testing>' }}
-        '''
-        tmpl = env.from_string(tmplsource)
-        assert tmpl.render(val=True).split()[0] == 'Markup'
-        assert tmpl.render(val=False).split()[0] == unicode.__name__
-
-        # looking at the source we should see <testing> there in raw
-        # (and then escaped as well)
-        env = Environment(extensions=['jinja2.ext.autoescape'])
-        pysource = env.compile(tmplsource, raw=True)
-        assert '<testing>\\n' in pysource
-
-        env = Environment(extensions=['jinja2.ext.autoescape'],
-                          autoescape=True)
-        pysource = env.compile(tmplsource, raw=True)
-        assert '&lt;testing&gt;\\n' in pysource
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ExtensionsTestCase))
-    suite.addTest(unittest.makeSuite(InternationalizationTestCase))
-    suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
-    suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py
deleted file mode 100644
index b59c9e3..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.filters
-    ~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests for the jinja filters.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Markup, Environment
-
-env = Environment()
-
-
-class FilterTestCase(JinjaTestCase):
-
-    def test_capitalize(self):
-        tmpl = env.from_string('{{ "foo bar"|capitalize }}')
-        assert tmpl.render() == 'Foo bar'
-
-    def test_center(self):
-        tmpl = env.from_string('{{ "foo"|center(9) }}')
-        assert tmpl.render() == '   foo   '
-
-    def test_default(self):
-        tmpl = env.from_string(
-            "{{ missing|default('no') }}|{{ false|default('no') }}|"
-            "{{ false|default('no', true) }}|{{ given|default('no') }}"
-        )
-        assert tmpl.render(given='yes') == 'no|False|no|yes'
-
-    def test_dictsort(self):
-        tmpl = env.from_string(
-            '{{ foo|dictsort }}|'
-            '{{ foo|dictsort(true) }}|'
-            '{{ foo|dictsort(false, "value") }}'
-        )
-        out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
-        assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
-                       "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
-                       "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
-
-    def test_batch(self):
-        tmpl = env.from_string("{{ foo|batch(3)|list }}|"
-                               "{{ foo|batch(3, 'X')|list }}")
-        out = tmpl.render(foo=range(10))
-        assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
-                       "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
-
-    def test_slice(self):
-        tmpl = env.from_string('{{ foo|slice(3)|list }}|'
-                               '{{ foo|slice(3, "X")|list }}')
-        out = tmpl.render(foo=range(10))
-        assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
-                       "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
-
-    def test_escape(self):
-        tmpl = env.from_string('''{{ '<">&'|escape }}''')
-        out = tmpl.render()
-        assert out == '&lt;&#34;&gt;&amp;'
-
-    def test_striptags(self):
-        tmpl = env.from_string('''{{ foo|striptags }}''')
-        out = tmpl.render(foo='  <p>just a small   \n <a href="#">'
-                          'example</a> link</p>\n<p>to a webpage</p> '
-                          '<!-- <p>and some commented stuff</p> -->')
-        assert out == 'just a small example link to a webpage'
-
-    def test_filesizeformat(self):
-        tmpl = env.from_string(
-            '{{ 100|filesizeformat }}|'
-            '{{ 1000|filesizeformat }}|'
-            '{{ 1000000|filesizeformat }}|'
-            '{{ 1000000000|filesizeformat }}|'
-            '{{ 1000000000000|filesizeformat }}|'
-            '{{ 100|filesizeformat(true) }}|'
-            '{{ 1000|filesizeformat(true) }}|'
-            '{{ 1000000|filesizeformat(true) }}|'
-            '{{ 1000000000|filesizeformat(true) }}|'
-            '{{ 1000000000000|filesizeformat(true) }}'
-        )
-        out = tmpl.render()
-        assert out == (
-            '100 Bytes|1.0 KB|1.0 MB|1.0 GB|1000.0 GB|'
-            '100 Bytes|1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
-        )
-
-    def test_first(self):
-        tmpl = env.from_string('{{ foo|first }}')
-        out = tmpl.render(foo=range(10))
-        assert out == '0'
-
-    def test_float(self):
-        tmpl = env.from_string('{{ "42"|float }}|'
-                               '{{ "ajsghasjgd"|float }}|'
-                               '{{ "32.32"|float }}')
-        out = tmpl.render()
-        assert out == '42.0|0.0|32.32'
-
-    def test_format(self):
-        tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
-        out = tmpl.render()
-        assert out == 'a|b'
-
-    def test_indent(self):
-        tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
-        text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
-        out = tmpl.render(foo=text)
-        assert out == ('foo bar foo bar\n  foo bar foo bar|  '
-                       'foo bar foo bar\n  foo bar foo bar')
-
-    def test_int(self):
-        tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
-                               '{{ "32.32"|int }}')
-        out = tmpl.render()
-        assert out == '42|0|32'
-
-    def test_join(self):
-        tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
-        out = tmpl.render()
-        assert out == '1|2|3'
-
-        env2 = Environment(autoescape=True)
-        tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
-        assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
-
-    def test_last(self):
-        tmpl = env.from_string('''{{ foo|last }}''')
-        out = tmpl.render(foo=range(10))
-        assert out == '9'
-
-    def test_length(self):
-        tmpl = env.from_string('''{{ "hello world"|length }}''')
-        out = tmpl.render()
-        assert out == '11'
-
-    def test_lower(self):
-        tmpl = env.from_string('''{{ "FOO"|lower }}''')
-        out = tmpl.render()
-        assert out == 'foo'
-
-    def test_pprint(self):
-        from pprint import pformat
-        tmpl = env.from_string('''{{ data|pprint }}''')
-        data = range(1000)
-        assert tmpl.render(data=data) == pformat(data)
-
-    def test_random(self):
-        tmpl = env.from_string('''{{ seq|random }}''')
-        seq = range(100)
-        for _ in range(10):
-            assert int(tmpl.render(seq=seq)) in seq
-
-    def test_reverse(self):
-        tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
-                               '{{ [1, 2, 3]|reverse|list }}')
-        assert tmpl.render() == 'raboof|[3, 2, 1]'
-
-    def test_string(self):
-        x = [1, 2, 3, 4, 5]
-        tmpl = env.from_string('''{{ obj|string }}''')
-        assert tmpl.render(obj=x) == unicode(x)
-
-    def test_title(self):
-        tmpl = env.from_string('''{{ "foo bar"|title }}''')
-        assert tmpl.render() == "Foo Bar"
-
-    def test_truncate(self):
-        tmpl = env.from_string(
-            '{{ data|truncate(15, true, ">>>") }}|'
-            '{{ data|truncate(15, false, ">>>") }}|'
-            '{{ smalldata|truncate(15) }}'
-        )
-        out = tmpl.render(data='foobar baz bar' * 1000,
-                          smalldata='foobar baz bar')
-        assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar'
-
-    def test_upper(self):
-        tmpl = env.from_string('{{ "foo"|upper }}')
-        assert tmpl.render() == 'FOO'
-
-    def test_urlize(self):
-        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
-        assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
-                                'http://www.example.com/</a> bar'
-
-    def test_wordcount(self):
-        tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
-        assert tmpl.render() == '3'
-
-    def test_block(self):
-        tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
-        assert tmpl.render() == '&lt;hehe&gt;'
-
-    def test_chaining(self):
-        tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
-        assert tmpl.render() == '&lt;FOO&gt;'
-
-    def test_sum(self):
-        tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
-        assert tmpl.render() == '21'
-
-    def test_abs(self):
-        tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
-        assert tmpl.render() == '1|1', tmpl.render()
-
-    def test_round_positive(self):
-        tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
-                               "{{ 2.1234|round(3, 'floor') }}|"
-                               "{{ 2.1|round(0, 'ceil') }}")
-        assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
-
-    def test_round_negative(self):
-        tmpl = env.from_string('{{ 21.3|round(-1)}}|'
-                               "{{ 21.3|round(-1, 'ceil')}}|"
-                               "{{ 21.3|round(-1, 'floor')}}")
-        assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
-
-    def test_xmlattr(self):
-        tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
-                               "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
-        out = tmpl.render().split()
-        assert len(out) == 3
-        assert 'foo="42"' in out
-        assert 'bar="23"' in out
-        assert 'blub:blub="&lt;?&gt;"' in out
-
-    def test_sort1(self):
-        tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
-        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
-
-    def test_sort2(self):
-        tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort(false, true)) }}')
-        assert tmpl.render() == 'AbcD'
-
-    def test_groupby(self):
-        tmpl = env.from_string('''
-        {%- for grouper, list in [{'foo': 1, 'bar': 2},
-                                  {'foo': 2, 'bar': 3},
-                                  {'foo': 1, 'bar': 1},
-                                  {'foo': 3, 'bar': 4}]|groupby('foo') -%}
-            {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
-        {%- endfor %}''')
-        assert tmpl.render().split('|') == [
-            "1: 1, 2: 1, 1",
-            "2: 2, 3",
-            "3: 3, 4",
-            ""
-        ]
-
-    def test_filtertag(self):
-        tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
-                               "foobar{% endfilter %}")
-        assert tmpl.render() == 'fooBAR'
-
-    def test_replace(self):
-        env = Environment()
-        tmpl = env.from_string('{{ string|replace("o", 42) }}')
-        assert tmpl.render(string='<foo>') == '<f4242>'
-        env = Environment(autoescape=True)
-        tmpl = env.from_string('{{ string|replace("o", 42) }}')
-        assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
-        tmpl = env.from_string('{{ string|replace("<", 42) }}')
-        assert tmpl.render(string='<foo>') == '42foo&gt;'
-        tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
-        assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
-
-    def test_forceescape(self):
-        tmpl = env.from_string('{{ x|forceescape }}')
-        assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
-
-    def test_safe(self):
-        env = Environment(autoescape=True)
-        tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
-        assert tmpl.render() == '<div>foo</div>'
-        tmpl = env.from_string('{{ "<div>foo</div>" }}')
-        assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
-
-    def test_sort2(self):
-        tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
-        assert tmpl.render() == "['Bar', 'blah', 'foo']"
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(FilterTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py
deleted file mode 100644
index c785606..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.imports
-    ~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests the import features (with includes).
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment, DictLoader
-from jinja2.exceptions import TemplateNotFound, TemplatesNotFound
-
-
-test_env = Environment(loader=DictLoader(dict(
-    module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
-    header='[{{ foo }}|{{ 23 }}]',
-    o_printer='({{ o }})'
-)))
-test_env.globals['bar'] = 23
-
-
-class ImportsTestCase(JinjaTestCase):
-
-    def test_context_imports(self):
-        t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
-        assert t.render(foo=42) == '[42|23]'
-        t = test_env.from_string('{% from "module" import test %}{{ test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
-        assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
-        assert t.render(foo=42) == '[42|23]'
-
-    def test_trailing_comma(self):
-        test_env.from_string('{% from "foo" import bar, baz with context %}')
-        test_env.from_string('{% from "foo" import bar, baz, with context %}')
-        test_env.from_string('{% from "foo" import bar, with context %}')
-        test_env.from_string('{% from "foo" import bar, with, context %}')
-        test_env.from_string('{% from "foo" import bar, with with context %}')
-
-    def test_exports(self):
-        m = test_env.from_string('''
-            {% macro toplevel() %}...{% endmacro %}
-            {% macro __private() %}...{% endmacro %}
-            {% set variable = 42 %}
-            {% for item in [1] %}
-                {% macro notthere() %}{% endmacro %}
-            {% endfor %}
-        ''').module
-        assert m.toplevel() == '...'
-        assert not hasattr(m, '__missing')
-        assert m.variable == 42
-        assert not hasattr(m, 'notthere')
-
-
-class IncludesTestCase(JinjaTestCase):
-
-    def test_context_include(self):
-        t = test_env.from_string('{% include "header" %}')
-        assert t.render(foo=42) == '[42|23]'
-        t = test_env.from_string('{% include "header" with context %}')
-        assert t.render(foo=42) == '[42|23]'
-        t = test_env.from_string('{% include "header" without context %}')
-        assert t.render(foo=42) == '[|23]'
-
-    def test_choice_includes(self):
-        t = test_env.from_string('{% include ["missing", "header"] %}')
-        assert t.render(foo=42) == '[42|23]'
-
-        t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
-        assert t.render(foo=42) == ''
-
-        t = test_env.from_string('{% include ["missing", "missing2"] %}')
-        self.assert_raises(TemplateNotFound, t.render)
-        try:
-            t.render()
-        except TemplatesNotFound, e:
-            assert e.templates == ['missing', 'missing2']
-            assert e.name == 'missing2'
-        else:
-            assert False, 'thou shalt raise'
-
-        def test_includes(t, **ctx):
-            ctx['foo'] = 42
-            assert t.render(ctx) == '[42|23]'
-
-        t = test_env.from_string('{% include ["missing", "header"] %}')
-        test_includes(t)
-        t = test_env.from_string('{% include x %}')
-        test_includes(t, x=['missing', 'header'])
-        t = test_env.from_string('{% include [x, "header"] %}')
-        test_includes(t, x='missing')
-        t = test_env.from_string('{% include x %}')
-        test_includes(t, x='header')
-        t = test_env.from_string('{% include x %}')
-        test_includes(t, x='header')
-        t = test_env.from_string('{% include [x] %}')
-        test_includes(t, x='header')
-
-    def test_include_ignoring_missing(self):
-        t = test_env.from_string('{% include "missing" %}')
-        self.assert_raises(TemplateNotFound, t.render)
-        for extra in '', 'with context', 'without context':
-            t = test_env.from_string('{% include "missing" ignore missing ' +
-                                     extra + ' %}')
-            assert t.render() == ''
-
-    def test_context_include_with_overrides(self):
-        env = Environment(loader=DictLoader(dict(
-            main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
-            item="{{ item }}"
-        )))
-        assert env.get_template("main").render() == "123"
-
-    def test_unoptimized_scopes(self):
-        t = test_env.from_string("""
-            {% macro outer(o) %}
-            {% macro inner() %}
-            {% include "o_printer" %}
-            {% endmacro %}
-            {{ inner() }}
-            {% endmacro %}
-            {{ outer("FOO") }}
-        """)
-        assert t.render().strip() == '(FOO)'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ImportsTestCase))
-    suite.addTest(unittest.makeSuite(IncludesTestCase))
-    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py
deleted file mode 100644
index 87b4a59..0000000
--- a/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.inheritance
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Tests the template inheritance feature.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import time
-import tempfile
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
-from jinja2 import Environment, DictLoader
-from jinja2.exceptions import TemplateSyntaxError
-
-
-LAYOUTTEMPLATE = '''\
-|{% block block1 %}block 1 from layout{% endblock %}
-|{% block block2 %}block 2 from layout{% endblock %}
-|{% block block3 %}
-{% block block4 %}nested block 4 from layout{% endblock %}
-{% endblock %}|'''
-
-LEVEL1TEMPLATE = '''\
-{% extends "layout" %}
-{% block block1 %}block 1 from level1{% endblock %}'''
-
-LEVEL2TEMPLATE = '''\
-{% extends "level1" %}
-{% block block2 %}{% block block5 %}nested block 5 from level2{%
-endblock %}{% endblock %}'''
-
-LEVEL3TEMPLATE = '''\
-{% extends "level2" %}
-{% block block5 %}block 5 from level3{% endblock %}
-{% block block4 %}block 4 from level3{% endblock %}
-'''
-
-LEVEL4TEMPLATE = '''\
-{% extends "level3" %}
-{% block block3 %}block 3 from level4{% endblock %}
-'''
-
-WORKINGTEMPLATE = '''\
-{% extends "layout" %}
-{% block block1 %}
-  {% if false %}
-    {% block block2 %}
-      this should workd
-    {% endblock %}
-  {% endif %}
-{% endblock %}
-'''
-
-env = Environment(loader=DictLoader({
-    'layout':       LAYOUTTEMPLATE,
-    'level1':       LEVEL1TEMPLATE,
-    'level2':       LEVEL2TEMPLATE,
-    'level3':       LEVEL3TEMPLATE,
-    'level4':       LEVEL4TEMPLATE,
-    'working':      WORKINGTEMPLATE
-}), trim_blocks=True)
-
-
-class InheritanceTestCase(JinjaTestCase):
-
-    def test_layout(self):
-        tmpl = env.get_template('layout')
-        assert tmpl.render() == ('|block 1 from layout|block 2 from '
-                                 'layout|nested block 4 from layout|')
-
-    def test_level1(self):
-        tmpl = env.get_template('level1')
-        assert tmpl.render() == ('|block 1 from level1|block 2 from '
-                                 'layout|nested block 4 from layout|')
-
-    def test_level2(self):
-        tmpl = env.get_template('level2')
-        assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
-                                 'level2|nested block 4 from layout|')
-
-    def test_level3(self):
-        tmpl = env.get_template('level3')
-        assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
-                                 'block 4 from level3|')
-
-    def test_level4(sel):
-        tmpl = env.get_template('level4')
-        assert tmpl.render() == ('|block 1 from level1|block 5 from '
-                                 'level3|block 3 from level4|')
-
-    def test_super(self):
-        env = Environment(loader=DictLoader({
-            'a': '{% block intro %}INTRO{% endblock %}|'
-                 'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
-            'b': '{% extends "a" %}{% block data %}({{ '
-                 'super() }}){% endblock %}',
-            'c': '{% extends "b" %}{% block intro %}--{{ '
-                 'super() }}--{% endblock %}\n{% block data '
-                 '%}[{{ super() }}]{% endblock %}'
-        }))
-        tmpl = env.get_template('c')
-        assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
-
-    def test_working(self):
-        tmpl = env.get_template('working')
-
-    def test_reuse_blocks(self):
-        tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
-                               '{% endblock %}|{{ self.foo() }}')
-        assert tmpl.render() == '42|42|42'
-
-    def test_preserve_blocks(self):
-        env = Environment(loader=DictLoader({
-            'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
-            'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
-        }))
-        tmpl = env.get_template('b')
-        assert tmpl.render() == 'BA'
-
-    def test_dynamic_inheritance(self):
-        env = Environment(loader=DictLoader({
-            'master1': 'MASTER1{% block x %}{% endblock %}',
-            'master2': 'MASTER2{% block x %}{% endblock %}',
-            'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
-        }))
-        tmpl = env.get_template('child')
-        for m in range(1, 3):
-            assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
-
-    def test_multi_inheritance(self):
-        env = Environment(loader=DictLoader({
-            'master1': 'MASTER1{% block x %}{% endblock %}',
-            'master2': 'MASTER2{% block x %}{% endblock %}',
-            'child': '''{% if master %}{% extends master %}{% else %}{% extends
-                        'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
-        }))
-        tmpl = env.get_template('child')
-        assert tmpl.render(master='master2') == 'MASTER2CHILD'
-        assert tmpl.render(master='master1') == 'MASTER1CHILD'
-        assert tmpl.render() == 'MASTER1CHILD'
-
-    def test_scoped_block(self):
-        env = Environment(loader=DictLoader({
-            'master.html': '{% for item in seq %}[{% block item scoped %}'
-                           '{% endblock %}]{% endfor %}'
-        }))
-        t = env.from_string('{% extends "master.html" %}{% block item %}'
-                            '{{ item }}{% endblock %}')
-        assert t.render(seq=range(5)) == '[0][1][2][3][4]'
-
-    def test_super_in_scoped_block(self):
-        env = Environment(loader=DictLoader({
-            'master.html': '{% for item in seq %}[{% block item scoped %}'
-                           '{{ item }}{% endblock %}]{% endfor %}'
-        }))
-        t = env.from_string('{% extends "master.html" %}{% block item %}'
-                            '{{ super() }}|{{ item * 2 }}{% endblock %}')
-        assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]'
-
-
-class BugFixTestCase(JinjaTestCase):
-
-    def test_fixed_macro_scoping_bug(self):
-        assert Environment(loader=DictLoader({
-            'test.html': '''\
-        {% extends 'details.html' %}
-
-        {% macro my_macro() %}
-        my_macro
-        {% endmacro %}
-
-        {% block inner_box %}
-            {{ my_macro() }}
-        {% endblock %}
-            ''',
-            'details.html': '''\
-        {% extends 'standard.html' %}
-
-        {% macro my_macro() %}
-        my_macro
-        {% endmacro %}
-
-        {% block content %}
-            {% block outer_box %}
-                outer_box
-                {% block inner_box %}
-                    inner_box
-                {% endblock %}
-            {% endblock %}
-        {% endblock %}
-        ''',
-            'standard.html': '''
-        {% block content %}&nbsp;{% endblock %}
-        '''
-        })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(InheritanceTestCase))
-    suite.addTest(unittest.makeSuite(BugFixTestCase))
-    return suite


[43/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py
new file mode 100644
index 0000000..fd0ea68
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_broken_reraising.py
@@ -0,0 +1,21 @@
+from lib2to3 import fixer_base, pytree
+from lib2to3.fixer_util import Name, BlankLine, Name, Attr, ArgList
+
+
+class FixBrokenReraising(fixer_base.BaseFix):
+    PATTERN = """
+    raise_stmt< 'raise' any ',' val=any ',' tb=any >
+    """
+
+    # run before the broken 2to3 checker with the same goal
+    # tries to rewrite it with a rule that does not work out for jinja
+    run_order = 1
+
+    def transform(self, node, results):
+        tb = results['tb'].clone()
+        tb.prefix = ''
+        with_tb = Attr(results['val'].clone(), Name('with_traceback')) + \
+                  [ArgList([tb])]
+        new = pytree.Node(self.syms.simple_stmt, [Name("raise")] + with_tb)
+        new.prefix = node.prefix
+        return new

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py
new file mode 100644
index 0000000..5d35e50
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/custom_fixers/fix_xrange2.py
@@ -0,0 +1,11 @@
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import Name, BlankLine
+
+
+# whyever this is necessary..
+
+class FixXrange2(fixer_base.BaseFix):
+    PATTERN = "'xrange'"
+
+    def transform(self, node, results):
+        node.replace(Name('range', prefix=node.prefix))

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/Makefile
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/Makefile b/ambari-common/src/main/python/ambari_jinja2/docs/Makefile
new file mode 100644
index 0000000..5e24ec1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/Makefile
@@ -0,0 +1,75 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview over all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+
+clean:
+	-rm -rf _build/*
+
+html:
+	mkdir -p _build/html _build/doctrees
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+	@echo
+	@echo "Build finished. The HTML pages are in _build/html."
+
+pickle:
+	mkdir -p _build/pickle _build/doctrees
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files"
+
+json:
+	mkdir -p _build/json _build/doctrees
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
+	@echo
+	@echo "Build finished; now you can process the json files"
+
+web: pickle
+
+htmlhelp:
+	mkdir -p _build/htmlhelp _build/doctrees
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in _build/htmlhelp."
+
+latex:
+	mkdir -p _build/latex _build/doctrees
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in _build/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	mkdir -p _build/changes _build/doctrees
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
+	@echo
+	@echo "The overview file is in _build/changes."
+
+linkcheck:
+	mkdir -p _build/linkcheck _build/doctrees
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in _build/linkcheck/output.txt."

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js b/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js
new file mode 100644
index 0000000..1c04218
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_static/jinja.js
@@ -0,0 +1,26 @@
+$(function() {
+
+  var
+    toc = $('#toc').show(),
+    items = $('#toc > ul').hide();
+
+  $('#toc h3')
+    .click(function() {
+      if (items.is(':visible')) {
+        items.animate({
+          height:     'hide',
+          opacity:    'hide'
+        }, 300, function() {
+          toc.removeClass('expandedtoc');
+        });
+      }
+      else {
+        items.animate({
+          height:     'show',
+          opacity:    'show'
+        }, 400);
+        toc.addClass('expandedtoc');
+      }
+    });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css b/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css
new file mode 100644
index 0000000..fb633d8
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_static/print.css
@@ -0,0 +1,5 @@
+div.header, div.relnav, #toc { display: none; }
+#contentwrapper { padding: 0; margin: 0; border: none; }
+body { color: black; background-color: white; }
+div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
+div.footer a { text-decoration: none; }

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css b/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css
new file mode 100644
index 0000000..a1c4d59
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_static/style.css
@@ -0,0 +1,390 @@
+body {
+    background-color: #222;
+    margin: 0;
+    padding: 0;
+    font-family: 'Georgia', serif;
+    font-size: 15px;
+    color: #eee;
+}
+
+div.footer {
+    border-top: 1px solid #111;
+    padding: 8px;
+    font-size: 11px;
+    text-align: center;
+    letter-spacing: 0.5px;
+}
+
+div.footer a {
+    color: #eee;
+}
+
+div.header {
+    margin: 0 -15px 0 -15px;
+    background: url(headerbg.png) repeat-x;
+    border-top: 6px solid #D20000;
+}
+
+div.relnav {
+    border-bottom: 1px solid #111;
+    background: url(navigation.png);
+    margin: 0 -15px 0 -15px;
+    padding: 2px 20px 0 28px;
+    line-height: 25px;
+    color: #aaa;
+    font-size: 12px;
+    text-align: center;
+}
+
+div.relnav a {
+    color: #eee;
+    font-weight: bold;
+    text-decoration: none;
+}
+
+div.relnav a:hover {
+    text-decoration: underline;
+}
+
+#content {
+    background-color: white;
+    color: #111;
+    border-bottom: 1px solid black;
+    background: url(watermark.png) center 0;
+    padding: 0 15px 0 15px;
+    margin: 0;
+}
+
+h1 {
+    margin: 0;
+    padding: 15px 0 0 0;
+}
+
+h1.heading {
+    margin: 0;
+    padding: 0;
+    height: 80px;
+}
+
+h1.heading:hover {
+    background: #222;
+}
+
+h1.heading a {
+    background: url(jinjabanner.png) no-repeat center 0;
+    display: block;
+    width: 100%;
+    height: 80px;
+}
+
+h1.heading a:focus {
+    -moz-outline: none;
+    outline: none;
+}
+
+h1.heading span {
+    display: none;
+}
+
+#jinjalogo {
+    background-image: url(jinjalogo.png);
+    background-repeat: no-repeat;
+    width: 400px;
+    height: 160px;
+}
+
+#contentwrapper {
+    max-width: 680px;
+    padding: 0 18px 20px 18px;
+    margin: 0 auto 0 auto;
+    border-right: 1px solid #eee;
+    border-left: 1px solid #eee;
+    background: url(watermark_blur.png) center -114px;
+}
+
+#contentwrapper h2,
+#contentwrapper h2 a {
+    color: #222;
+    font-size: 24px;
+    margin: 20px 0 0 0;
+}
+
+#contentwrapper h3,
+#contentwrapper h3 a {
+    color: #b41717;
+    font-size: 20px;
+    margin: 20px 0 0 0;
+}
+
+table.docutils {
+    border-collapse: collapse;
+    border: 2px solid #aaa;
+    margin: 0.5em 1.5em 0.5em 1.5em;
+}
+
+table.docutils td {
+    padding: 2px;
+    border: 1px solid #ddd;
+}
+
+p, li, dd, dt, blockquote {
+    color: #333;
+}
+
+blockquote {
+    margin: 10px 0 10px 20px;
+}
+
+p {
+    line-height: 20px;
+    margin-bottom: 0;
+    margin-top: 10px;
+}
+
+hr {
+    border-top: 1px solid #ccc;
+    border-bottom: 0;
+    border-right: 0;
+    border-left: 0;
+    margin-bottom: 10px;
+    margin-top: 20px;
+}
+
+dl {
+    margin-left: 10px;
+}
+
+li, dt {
+    margin-top: 5px;
+}
+
+dt {
+    font-weight: bold;
+    color: #000;
+}
+
+dd {
+    margin-top: 10px;
+    line-height: 20px;
+}
+
+th {
+    text-align: left;
+    padding: 3px;
+    background-color: #f2f2f2;
+}
+
+a {
+    color: #b41717;
+}
+
+a:hover {
+    color: #444;
+}
+
+pre {
+    background: #ededed url(metal.png);
+    border-top: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+    padding: 5px;
+    font-size: 13px;
+    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+}
+
+tt {
+    font-size: 13px;
+    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+    color: black;
+    padding: 1px 2px 1px 2px;
+    background-color: #fafafa;
+    border-bottom: 1px solid #eee;
+}
+
+a.reference:hover tt {
+    border-bottom-color: #aaa;
+}
+
+cite {
+    /* abusing <cite>, it's generated by ReST for `x` */
+    font-size: 13px;
+    font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+    font-weight: bold;
+    font-style: normal;
+}
+
+div.admonition {
+    margin: 10px 0 10px 0;
+    padding: 10px 10px 10px 60px;
+    border: 1px solid #ccc;
+}
+
+div.admonition p.admonition-title {
+    background-color: #b41717;
+    color: white;
+    margin: -10px -10px 10px -60px;
+    padding: 4px 10px 4px 10px;
+    font-weight: bold;
+    font-size: 15px;
+}
+
+div.admonition p.admonition-title a {
+    color: white!important;
+}
+
+div.admonition-note {
+    background: url(note.png) no-repeat 10px 40px;
+}
+
+div.admonition-implementation {
+    background: url(implementation.png) no-repeat 10px 40px;
+}
+
+a.headerlink {
+    color: #B4B4B4!important;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none!important;
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+dt:hover > a.headerlink {
+    visibility: visible;
+}
+
+a.headerlink:hover {
+    background-color: #B4B4B4;
+    color: #F0F0F0!important;
+}
+
+table.indextable {
+    width: 100%;
+}
+
+table.indextable td {
+    vertical-align: top;
+    width: 50%;
+}
+
+table.indextable dl dd {
+    font-size: 11px;
+}
+
+table.indextable dl dd a {
+    color: #000;
+}
+
+dl.function dt,
+dl.class dt,
+dl.exception dt,
+dl.method dt,
+dl.attribute dt {
+    font-weight: normal;
+}
+
+dt .descname {
+    font-weight: bold;
+    margin-right: 4px;
+}
+
+dt .descname, dt .descclassname {
+    padding: 0;
+    background: transparent;
+    border-bottom: 1px solid #111;
+}
+
+dt .descclassname {
+    margin-left: 2px;
+}
+
+dl dt big {
+    font-size: 100%;
+}
+
+ul.search {
+    margin: 10px 0 0 30px;
+    padding: 0;
+}
+
+ul.search li {
+    margin: 10px 0 0 0;
+    padding: 0;
+}
+
+ul.search div.context {
+    font-size: 12px;
+    padding: 4px 0 0 20px;
+    color: #888;
+}
+
+span.highlight {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+#toc {
+    margin: 0 -17px 0 -17px;
+    display: none;
+}
+
+#toc h3 {
+    float: right;
+    margin: 5px 5px 0 0;
+    padding: 0;
+    font-size: 12px;
+    color: #777;
+}
+
+#toc h3:hover {
+    color: #333;
+    cursor: pointer;
+}
+
+.expandedtoc {
+    background: #222 url(darkmetal.png);
+    border-bottom: 1px solid #111;
+    outline-bottom: 1px solid #000;
+    padding: 5px;
+}
+
+.expandedtoc h3 {
+    color: #aaa;
+    margin: 0!important;
+}
+
+.expandedtoc h3:hover {
+    color: white!important;
+}
+
+#tod h3:hover {
+    color: white;
+}
+
+#toc a {
+    color: #ddd;
+    text-decoration: none;
+}
+
+#toc a:hover {
+    color: white;
+    text-decoration: underline;
+}
+
+#toc ul {
+    margin: 5px 0 12px 17px;
+    padding: 0 7px 0 7px;
+}
+
+#toc ul ul {
+    margin-bottom: 0;
+}
+
+#toc ul li {
+    margin: 2px 0 0 0;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html
new file mode 100644
index 0000000..9add6e9
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/genindex.html
@@ -0,0 +1,36 @@
+{% extends "layout.html" %}
+{% set title = 'Index' %}
+{% block body %}
+
+  <h1 id="index">Index</h1>
+
+  {% for key, dummy in genindexentries -%}
+  <a href="#{{ key }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %}
+  {%- endfor %}
+  <hr>
+
+  {% for key, entries in genindexentries %}
+    <h2 id="{{ key }}">{{ key }}</h2>
+    <table class="indextable"><tr>
+    {%- for column in entries|slice(2) if column %}
+      <td><dl>
+      {%- for entryname, (links, subitems) in column %}
+        <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
+          {% for link in links[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor %}
+          {%- else %}{{ entryname|e }}{% endif %}</dt>
+        {%- if subitems %}
+        <dd><dl>
+          {%- for subentryname, subentrylinks in subitems %}
+          <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
+          {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor -%}
+          </dt>
+          {%- endfor %}
+        </dl></dd>
+        {%- endif -%}
+      {%- endfor %}
+      </dl></td>
+    {%- endfor %}
+    </tr></table>
+  {% endfor %}
+
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html
new file mode 100644
index 0000000..f682f90
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/layout.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <title>Jinja2 Documentation</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}" type="text/css">
+    <link rel="stylesheet" href="{{ pathto('_static/print.css', 1) }}" type="text/css" media="print">
+    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css">
+    {%- if builder != 'htmlhelp' %}
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:   '{{ pathto("", 1) }}',
+        VERSION:    '{{ release }}'
+      };
+    </script>
+    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/jinja.js', 1) }}"></script>
+    {%- endif %}
+    {%- if use_opensearch and builder != 'htmlhelp' %}
+    <link rel="search" type="application/opensearchdescription+xml"
+          title="Search within {{ docstitle }}"
+          href="{{ pathto('_static/opensearch.xml', 1) }}">
+    {%- endif %}
+    {%- if hasdoc('about') %}
+    <link rel="author" title="About these documents" href="{{ pathto('about') }}">
+    {%- endif %}
+    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}">
+    <link rel="index" title="Global index" href="{{ pathto('genindex') }}">
+    <link rel="search" title="Search" href="{{ pathto('search') }}">
+    {%- if hasdoc('copyright') %}
+    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}">
+    {%- endif %}
+    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}">
+    {%- if parents %}
+    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}">
+    {%- endif %}
+    {%- if next %}
+    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}">
+    {%- endif %}
+    {%- if prev %}
+    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}">
+    {%- endif %}
+    {% block extrahead %}{% endblock %}
+  </head>
+  <body>
+    <div id="content">
+      <div class="header">
+        <h1 class="heading"><a href="{{ pathto('index') }}"
+          title="back to the documentation overview"><span>Jinja</span></a></h1>
+      </div>
+      <div class="relnav">
+        {%- if prev %}
+        <a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
+        {%- endif %}
+        <a href="{{ pathto(current_page_name) if current_page_name else '#' }}">{{ title }}</a>
+        {%- if next %}
+        | <a href="{{ next.link|e }}">{{ next.title }} &raquo;</a>
+        {%- endif %}
+      </div>
+      <div id="contentwrapper">
+        {%- if display_toc %}
+        <div id="toc">
+          <h3>Table Of Contents</h3>
+          {{ toc }}
+        </div>
+        {%- endif %}
+        {% block body %}{% endblock %}
+      </div>
+    </div>
+    <div class="footer">
+      © Copyright 2010 by the <a href="http://pocoo.org/">Pocoo Team</a>,
+      documentation generated by <a href="http://sphinx.pocoo.org/">Sphinx</a>
+    </div>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml
new file mode 100644
index 0000000..9f2fa42
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/opensearch.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>{{ project }}</ShortName>
+  <Description>Search {{ docstitle }}</Description>
+  <InputEncoding>utf-8</InputEncoding>
+  <Url type="text/html" method="get"
+       template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&amp;check_keywords=yes&amp;area=default"/>
+  <LongName>{{ docstitle }}</LongName>
+</OpenSearchDescription>

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html
new file mode 100644
index 0000000..ee6cad3
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/page.html
@@ -0,0 +1,4 @@
+{% extends 'layout.html' %}
+{% block body %}
+  {{ body }}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html
new file mode 100644
index 0000000..0c942b7
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/_templates/search.html
@@ -0,0 +1,35 @@
+{% extends "layout.html" %}
+{% set title = 'Search' %}
+{% block extrahead %}
+    <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
+{% endblock %}
+{% block body %}
+  <h1 id="search-documentation">Search</h1>
+  <p>
+    From here you can search these documents. Enter your search
+    words into the box below and click "search". Note that the search
+    function will automatically search for all of the words. Pages
+    containing less words won't appear in the result list.
+  </p>
+  <form action="" method="get"><p>
+    <input type="text" name="q" value="">
+    <input type="submit" value="search">
+  </p></form>
+  {% if search_performed %}
+    <h2>Search Results</h2>
+    {% if not search_results %}
+      <p>Your search did not match any results.</p>
+    {% endif %}
+  {% endif %}
+  <div id="search-results">
+  {% if search_results %}
+    <ul>
+    {% for href, caption, context in search_results %}
+      <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
+        <div class="context">{{ context|e }}</div>
+      </li>
+    {% endfor %}
+    </ul>
+  {% endif %}
+  </div>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/api.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/api.rst b/ambari-common/src/main/python/ambari_jinja2/docs/api.rst
new file mode 100644
index 0000000..92da04a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/api.rst
@@ -0,0 +1,787 @@
+API
+===
+
+.. module:: ambari_jinja2
+    :synopsis: public Jinja2 API
+
+This document describes the API to Jinja2 and not the template language.  It
+will be most useful as reference to those implementing the template interface
+to the application and not those who are creating Jinja2 templates.
+
+Basics
+------
+
+Jinja2 uses a central object called the template :class:`Environment`.
+Instances of this class are used to store the configuration, global objects
+and are used to load templates from the file system or other locations.
+Even if you are creating templates from strings by using the constructor of
+:class:`Template` class, an environment is created automatically for you,
+albeit a shared one.
+
+Most applications will create one :class:`Environment` object on application
+initialization and use that to load templates.  In some cases it's however
+useful to have multiple environments side by side, if different configurations
+are in use.
+
+The simplest way to configure Jinja2 to load templates for your application
+looks roughly like this::
+
+    from ambari_jinja2 import Environment, PackageLoader
+    env = Environment(loader=PackageLoader('yourapplication', 'templates'))
+
+This will create a template environment with the default settings and a
+loader that looks up the templates in the `templates` folder inside the
+`yourapplication` python package.  Different loaders are available
+and you can also write your own if you want to load templates from a
+database or other resources.
+
+To load a template from this environment you just have to call the
+:meth:`get_template` method which then returns the loaded :class:`Template`::
+
+    template = env.get_template('mytemplate.html')
+
+To render it with some variables, just call the :meth:`render` method::
+
+    print template.render(the='variables', go='here')
+
+Using a template loader rather then passing strings to :class:`Template`
+or :meth:`Environment.from_string` has multiple advantages.  Besides being
+a lot easier to use it also enables template inheritance.
+
+
+Unicode
+-------
+
+Jinja2 is using Unicode internally which means that you have to pass Unicode
+objects to the render function or bytestrings that only consist of ASCII
+characters.  Additionally newlines are normalized to one end of line
+sequence which is per default UNIX style (``\n``).
+
+Python 2.x supports two ways of representing string objects.  One is the
+`str` type and the other is the `unicode` type, both of which extend a type
+called `basestring`.  Unfortunately the default is `str` which should not
+be used to store text based information unless only ASCII characters are
+used.  With Python 2.6 it is possible to make `unicode` the default on a per
+module level and with Python 3 it will be the default.
+
+To explicitly use a Unicode string you have to prefix the string literal
+with a `u`: ``u'Hänsel und Gretel sagen Hallo'``.  That way Python will
+store the string as Unicode by decoding the string with the character
+encoding from the current Python module.  If no encoding is specified this
+defaults to 'ASCII' which means that you can't use any non ASCII identifier.
+
+To set a better module encoding add the following comment to the first or
+second line of the Python module using the Unicode literal::
+
+    # -*- coding: utf-8 -*-
+
+We recommend utf-8 as Encoding for Python modules and templates as it's
+possible to represent every Unicode character in utf-8 and because it's
+backwards compatible to ASCII.  For Jinja2 the default encoding of templates
+is assumed to be utf-8.
+
+It is not possible to use Jinja2 to process non-Unicode data.  The reason
+for this is that Jinja2 uses Unicode already on the language level.  For
+example Jinja2 treats the non-breaking space as valid whitespace inside
+expressions which requires knowledge of the encoding or operating on an
+Unicode string.
+
+For more details about Unicode in Python have a look at the excellent
+`Unicode documentation`_.
+
+Another important thing is how Jinja2 is handling string literals in
+templates.  A naive implementation would be using Unicode strings for
+all string literals but it turned out in the past that this is problematic
+as some libraries are typechecking against `str` explicitly.  For example
+`datetime.strftime` does not accept Unicode arguments.  To not break it
+completely Jinja2 is returning `str` for strings that fit into ASCII and
+for everything else `unicode`:
+
+>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
+>>> m.a
+'foo'
+>>> m.b
+u'f\xf6\xf6'
+
+
+.. _Unicode documentation: http://docs.python.org/dev/howto/unicode.html
+
+High Level API
+--------------
+
+The high-level API is the API you will use in the application to load and
+render Jinja2 templates.  The :ref:`low-level-api` on the other side is only
+useful if you want to dig deeper into Jinja2 or :ref:`develop extensions
+<jinja-extensions>`.
+
+.. autoclass:: Environment([options])
+    :members: from_string, get_template, select_template,
+              get_or_select_template, join_path, extend, compile_expression
+
+    .. attribute:: shared
+
+        If a template was created by using the :class:`Template` constructor
+        an environment is created automatically.  These environments are
+        created as shared environments which means that multiple templates
+        may have the same anonymous environment.  For all shared environments
+        this attribute is `True`, else `False`.
+
+    .. attribute:: sandboxed
+
+        If the environment is sandboxed this attribute is `True`.  For the
+        sandbox mode have a look at the documentation for the
+        :class:`~ambari_jinja2.sandbox.SandboxedEnvironment`.
+
+    .. attribute:: filters
+
+        A dict of filters for this environment.  As long as no template was
+        loaded it's safe to add new filters or remove old.  For custom filters
+        see :ref:`writing-filters`.  For valid filter names have a look at
+        :ref:`identifier-naming`.
+
+    .. attribute:: tests
+
+        A dict of test functions for this environment.  As long as no
+        template was loaded it's safe to modify this dict.  For custom tests
+        see :ref:`writing-tests`.  For valid test names have a look at
+        :ref:`identifier-naming`.
+
+    .. attribute:: globals
+
+        A dict of global variables.  These variables are always available
+        in a template.  As long as no template was loaded it's safe
+        to modify this dict.  For more details see :ref:`global-namespace`.
+        For valid object names have a look at :ref:`identifier-naming`.
+
+    .. automethod:: overlay([options])
+
+    .. method:: undefined([hint, obj, name, exc])
+
+        Creates a new :class:`Undefined` object for `name`.  This is useful
+        for filters or functions that may return undefined objects for
+        some operations.  All parameters except of `hint` should be provided
+        as keyword parameters for better readability.  The `hint` is used as
+        error message for the exception if provided, otherwise the error
+        message will be generated from `obj` and `name` automatically.  The exception
+        provided as `exc` is raised if something with the generated undefined
+        object is done that the undefined object does not allow.  The default
+        exception is :exc:`UndefinedError`.  If a `hint` is provided the
+        `name` may be ommited.
+
+        The most common way to create an undefined object is by providing
+        a name only::
+
+            return environment.undefined(name='some_name')
+
+        This means that the name `some_name` is not defined.  If the name
+        was from an attribute of an object it makes sense to tell the
+        undefined object the holder object to improve the error message::
+
+            if not hasattr(obj, 'attr'):
+                return environment.undefined(obj=obj, name='attr')
+
+        For a more complex example you can provide a hint.  For example
+        the :func:`first` filter creates an undefined object that way::
+
+            return environment.undefined('no first item, sequence was empty')            
+
+        If it the `name` or `obj` is known (for example because an attribute
+        was accessed) it shold be passed to the undefined object, even if
+        a custom `hint` is provided.  This gives undefined objects the
+        possibility to enhance the error message.
+
+.. autoclass:: Template
+    :members: module, make_module
+
+    .. attribute:: globals
+
+        The dict with the globals of that template.  It's unsafe to modify
+        this dict as it may be shared with other templates or the environment
+        that loaded the template.
+
+    .. attribute:: name
+
+        The loading name of the template.  If the template was loaded from a
+        string this is `None`.
+
+    .. attribute:: filename
+
+        The filename of the template on the file system if it was loaded from
+        there.  Otherwise this is `None`.
+
+    .. automethod:: render([context])
+
+    .. automethod:: generate([context])
+
+    .. automethod:: stream([context])
+
+
+.. autoclass:: ambari_jinja2.environment.TemplateStream()
+    :members: disable_buffering, enable_buffering, dump
+
+
+Autoescaping
+------------
+
+.. versionadded:: 2.4
+
+As of Jinja 2.4 the preferred way to do autoescaping is to enable the
+:ref:`autoescape-extension` and to configure a sensible default for
+autoescaping.  This makes it possible to enable and disable autoescaping
+on a per-template basis (HTML versus text for instance).
+
+Here a recommended setup that enables autoescaping for templates ending
+in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
+for all other extensions::
+
+    def guess_autoescape(template_name):
+        if template_name is None or '.' not in template_name:
+            return False
+        ext = template_name.rsplit('.', 1)[1]
+        return ext in ('html', 'htm', 'xml')
+
+    env = Environment(autoescape=guess_autoescape,
+                      loader=PackageLoader('mypackage'),
+                      extensions=['ambari_jinja2.ext.autoescape'])
+
+When implementing a guessing autoescape function, make sure you also
+accept `None` as valid template name.  This will be passed when generating
+templates from strings.
+
+Inside the templates the behaviour can be temporarily changed by using
+the `autoescape` block (see :ref:`autoescape-overrides`).
+
+
+.. _identifier-naming:
+
+Notes on Identifiers
+--------------------
+
+Jinja2 uses the regular Python 2.x naming rules.  Valid identifiers have to
+match ``[a-zA-Z_][a-zA-Z0-9_]*``.  As a matter of fact non ASCII characters
+are currently not allowed.  This limitation will probably go away as soon as
+unicode identifiers are fully specified for Python 3.
+
+Filters and tests are looked up in separate namespaces and have slightly
+modified identifier syntax.  Filters and tests may contain dots to group
+filters and tests by topic.  For example it's perfectly valid to add a
+function into the filter dict and call it `to.unicode`.  The regular
+expression for filter and test identifiers is
+``[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*```.
+
+
+Undefined Types
+---------------
+
+These classes can be used as undefined types.  The :class:`Environment`
+constructor takes an `undefined` parameter that can be one of those classes
+or a custom subclass of :class:`Undefined`.  Whenever the template engine is
+unable to look up a name or access an attribute one of those objects is
+created and returned.  Some operations on undefined values are then allowed,
+others fail.
+
+The closest to regular Python behavior is the `StrictUndefined` which
+disallows all operations beside testing if it's an undefined object.
+
+.. autoclass:: ambari_jinja2.Undefined()
+
+    .. attribute:: _undefined_hint
+
+        Either `None` or an unicode string with the error message for
+        the undefined object.
+
+    .. attribute:: _undefined_obj
+
+        Either `None` or the owner object that caused the undefined object
+        to be created (for example because an attribute does not exist).
+
+    .. attribute:: _undefined_name
+
+        The name for the undefined variable / attribute or just `None`
+        if no such information exists.
+
+    .. attribute:: _undefined_exception
+
+        The exception that the undefined object wants to raise.  This
+        is usually one of :exc:`UndefinedError` or :exc:`SecurityError`.
+
+    .. method:: _fail_with_undefined_error(\*args, \**kwargs)
+
+        When called with any arguments this method raises
+        :attr:`_undefined_exception` with an error message generated
+        from the undefined hints stored on the undefined object.
+
+.. autoclass:: ambari_jinja2.DebugUndefined()
+
+.. autoclass:: ambari_jinja2.StrictUndefined()
+
+Undefined objects are created by calling :attr:`undefined`.
+
+.. admonition:: Implementation
+
+    :class:`Undefined` objects are implemented by overriding the special
+    `__underscore__` methods.  For example the default :class:`Undefined`
+    class implements `__unicode__` in a way that it returns an empty
+    string, however `__int__` and others still fail with an exception.  To
+    allow conversion to int by returning ``0`` you can implement your own::
+
+        class NullUndefined(Undefined):
+            def __int__(self):
+                return 0
+            def __float__(self):
+                return 0.0
+
+    To disallow a method, just override it and raise
+    :attr:`~Undefined._undefined_exception`.  Because this is a very common
+    idom in undefined objects there is the helper method
+    :meth:`~Undefined._fail_with_undefined_error` that does the error raising
+    automatically.  Here a class that works like the regular :class:`Undefined`
+    but chokes on iteration::
+
+        class NonIterableUndefined(Undefined):
+            __iter__ = Undefined._fail_with_undefined_error
+
+
+The Context
+-----------
+
+.. autoclass:: ambari_jinja2.runtime.Context()
+    :members: resolve, get_exported, get_all
+
+    .. attribute:: parent
+
+        A dict of read only, global variables the template looks up.  These
+        can either come from another :class:`Context`, from the
+        :attr:`Environment.globals` or :attr:`Template.globals` or points
+        to a dict created by combining the globals with the variables
+        passed to the render function.  It must not be altered.
+
+    .. attribute:: vars
+
+        The template local variables.  This list contains environment and
+        context functions from the :attr:`parent` scope as well as local
+        modifications and exported variables from the template.  The template
+        will modify this dict during template evaluation but filters and
+        context functions are not allowed to modify it.
+
+    .. attribute:: environment
+
+        The environment that loaded the template.
+
+    .. attribute:: exported_vars
+
+        This set contains all the names the template exports.  The values for
+        the names are in the :attr:`vars` dict.  In order to get a copy of the
+        exported variables as dict, :meth:`get_exported` can be used.
+
+    .. attribute:: name
+
+        The load name of the template owning this context.
+
+    .. attribute:: blocks
+
+        A dict with the current mapping of blocks in the template.  The keys
+        in this dict are the names of the blocks, and the values a list of
+        blocks registered.  The last item in each list is the current active
+        block (latest in the inheritance chain).
+
+    .. attribute:: eval_ctx
+
+        The current :ref:`eval-context`.
+
+    .. automethod:: ambari_jinja2.runtime.Context.call(callable, \*args, \**kwargs)
+
+
+.. admonition:: Implementation
+
+    Context is immutable for the same reason Python's frame locals are
+    immutable inside functions.  Both Jinja2 and Python are not using the
+    context / frame locals as data storage for variables but only as primary
+    data source.
+
+    When a template accesses a variable the template does not define, Jinja2
+    looks up the variable in the context, after that the variable is treated
+    as if it was defined in the template.
+
+
+.. _loaders:
+
+Loaders
+-------
+
+Loaders are responsible for loading templates from a resource such as the
+file system.  The environment will keep the compiled modules in memory like
+Python's `sys.modules`.  Unlike `sys.modules` however this cache is limited in
+size by default and templates are automatically reloaded.
+All loaders are subclasses of :class:`BaseLoader`.  If you want to create your
+own loader, subclass :class:`BaseLoader` and override `get_source`.
+
+.. autoclass:: ambari_jinja2.BaseLoader
+    :members: get_source, load
+
+Here a list of the builtin loaders Jinja2 provides:
+
+.. autoclass:: ambari_jinja2.FileSystemLoader
+
+.. autoclass:: ambari_jinja2.PackageLoader
+
+.. autoclass:: ambari_jinja2.DictLoader
+
+.. autoclass:: ambari_jinja2.FunctionLoader
+
+.. autoclass:: ambari_jinja2.PrefixLoader
+
+.. autoclass:: ambari_jinja2.ChoiceLoader
+
+
+.. _bytecode-cache:
+
+Bytecode Cache
+--------------
+
+Jinja 2.1 and higher support external bytecode caching.  Bytecode caches make
+it possible to store the generated bytecode on the file system or a different
+location to avoid parsing the templates on first use.
+
+This is especially useful if you have a web application that is initialized on
+the first request and Jinja compiles many templates at once which slows down
+the application.
+
+To use a bytecode cache, instanciate it and pass it to the :class:`Environment`.
+
+.. autoclass:: ambari_jinja2.BytecodeCache
+    :members: load_bytecode, dump_bytecode, clear
+
+.. autoclass:: ambari_jinja2.bccache.Bucket
+    :members: write_bytecode, load_bytecode, bytecode_from_string,
+              bytecode_to_string, reset
+
+    .. attribute:: environment
+
+        The :class:`Environment` that created the bucket.
+
+    .. attribute:: key
+
+        The unique cache key for this bucket
+
+    .. attribute:: code
+
+        The bytecode if it's loaded, otherwise `None`.
+
+
+Builtin bytecode caches:
+
+.. autoclass:: ambari_jinja2.FileSystemBytecodeCache
+
+.. autoclass:: ambari_jinja2.MemcachedBytecodeCache
+
+
+Utilities
+---------
+
+These helper functions and classes are useful if you add custom filters or
+functions to a Jinja2 environment.
+
+.. autofunction:: ambari_jinja2.environmentfilter
+
+.. autofunction:: ambari_jinja2.contextfilter
+
+.. autofunction:: ambari_jinja2.evalcontextfilter
+
+.. autofunction:: ambari_jinja2.environmentfunction
+
+.. autofunction:: ambari_jinja2.contextfunction
+
+.. autofunction:: ambari_jinja2.evalcontextfunction
+
+.. function:: escape(s)
+
+    Convert the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in string `s`
+    to HTML-safe sequences.  Use this if you need to display text that might
+    contain such characters in HTML.  This function will not escaped objects
+    that do have an HTML representation such as already escaped data.
+
+    The return value is a :class:`Markup` string.
+
+.. autofunction:: ambari_jinja2.clear_caches
+
+.. autofunction:: ambari_jinja2.is_undefined
+
+.. autoclass:: ambari_jinja2.Markup([string])
+    :members: escape, unescape, striptags
+
+.. admonition:: Note
+
+    The Jinja2 :class:`Markup` class is compatible with at least Pylons and
+    Genshi.  It's expected that more template engines and framework will pick
+    up the `__html__` concept soon.
+
+
+Exceptions
+----------
+
+.. autoexception:: ambari_jinja2.TemplateError
+
+.. autoexception:: ambari_jinja2.UndefinedError
+
+.. autoexception:: ambari_jinja2.TemplateNotFound
+
+.. autoexception:: ambari_jinja2.TemplatesNotFound
+
+.. autoexception:: ambari_jinja2.TemplateSyntaxError
+
+    .. attribute:: message
+
+        The error message as utf-8 bytestring.
+
+    .. attribute:: lineno
+
+        The line number where the error occurred
+
+    .. attribute:: name
+
+        The load name for the template as unicode string.
+
+    .. attribute:: filename
+
+        The filename that loaded the template as bytestring in the encoding
+        of the file system (most likely utf-8 or mbcs on Windows systems).
+
+    The reason why the filename and error message are bytestrings and not
+    unicode strings is that Python 2.x is not using unicode for exceptions
+    and tracebacks as well as the compiler.  This will change with Python 3.
+
+.. autoexception:: ambari_jinja2.TemplateAssertionError
+
+
+.. _writing-filters:
+
+Custom Filters
+--------------
+
+Custom filters are just regular Python functions that take the left side of
+the filter as first argument and the the arguments passed to the filter as
+extra arguments or keyword arguments.
+
+For example in the filter ``{{ 42|myfilter(23) }}`` the function would be
+called with ``myfilter(42, 23)``.  Here for example a simple filter that can
+be applied to datetime objects to format them::
+
+    def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
+        return value.strftime(format)
+
+You can register it on the template environment by updating the
+:attr:`~Environment.filters` dict on the environment::
+
+    environment.filters['datetimeformat'] = datetimeformat
+
+Inside the template it can then be used as follows:
+
+.. sourcecode:: jinja
+
+    written on: {{ article.pub_date|datetimeformat }}
+    publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}
+
+Filters can also be passed the current template context or environment.  This
+is useful if a filter wants to return an undefined value or check the current
+:attr:`~Environment.autoescape` setting.  For this purpose three decorators
+exist: :func:`environmentfilter`, :func:`contextfilter` and
+:func:`evalcontextfilter`.
+
+Here a small example filter that breaks a text into HTML line breaks and
+paragraphs and marks the return value as safe HTML string if autoescaping is
+enabled::
+
+    import re
+    from ambari_jinja2 import environmentfilter, Markup, escape
+
+    _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
+
+    @evalcontextfilter
+    def nl2br(eval_ctx, value):
+        result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
+                              for p in _paragraph_re.split(escape(value)))
+        if eval_ctx.autoescape:
+            result = Markup(result)
+        return result
+
+Context filters work the same just that the first argument is the current
+active :class:`Context` rather then the environment.
+
+
+.. _eval-context:
+
+Evaluation Context
+------------------
+
+The evaluation context (short eval context or eval ctx) is a new object
+introducted in Jinja 2.4 that makes it possible to activate and deactivate
+compiled features at runtime.
+
+Currently it is only used to enable and disable the automatic escaping but
+can be used for extensions as well.
+
+In previous Jinja versions filters and functions were marked as
+environment callables in order to check for the autoescape status from the
+environment.  In new versions it's encouraged to check the setting from the
+evaluation context instead.
+
+Previous versions::
+
+    @environmentfilter
+    def filter(env, value):
+        result = do_something(value)
+        if env.autoescape:
+            result = Markup(result)
+        return result
+
+In new versions you can either use a :func:`contextfilter` and access the
+evaluation context from the actual context, or use a
+:func:`evalcontextfilter` which directly passes the evaluation context to
+the function::
+
+    @contextfilter
+    def filter(context, value):
+        result = do_something(value)
+        if context.eval_ctx.autoescape:
+            result = Markup(result)
+        return result
+
+    @evalcontextfilter
+    def filter(eval_ctx, value):
+        result = do_something(value)
+        if eval_ctx.autoescape:
+            result = Markup(result)
+        return result
+
+The evaluation context must not be modified at runtime.  Modifications
+must only happen with a :class:`nodes.EvalContextModifier` and
+:class:`nodes.ScopedEvalContextModifier` from an extension, not on the
+eval context object itself.
+
+.. autoclass:: ambari_jinja2.nodes.EvalContext
+
+   .. attribute:: autoescape
+
+      `True` or `False` depending on if autoescaping is active or not.
+
+   .. attribute:: volatile
+
+      `True` if the compiler cannot evaluate some expressions at compile
+      time.  At runtime this should always be `False`.
+
+
+.. _writing-tests:
+
+Custom Tests
+------------
+
+Tests work like filters just that there is no way for a test to get access
+to the environment or context and that they can't be chained.  The return
+value of a test should be `True` or `False`.  The purpose of a test is to
+give the template designers the possibility to perform type and conformability
+checks.
+
+Here a simple test that checks if a variable is a prime number::
+
+    import math
+
+    def is_prime(n):
+        if n == 2:
+            return True
+        for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
+            if n % i == 0:
+                return False
+        return True
+        
+
+You can register it on the template environment by updating the
+:attr:`~Environment.tests` dict on the environment::
+
+    environment.tests['prime'] = is_prime
+
+A template designer can then use the test like this:
+
+.. sourcecode:: jinja
+
+    {% if 42 is prime %}
+        42 is a prime number
+    {% else %}
+        42 is not a prime number
+    {% endif %}
+
+
+.. _global-namespace:
+
+The Global Namespace
+--------------------
+
+Variables stored in the :attr:`Environment.globals` dict are special as they
+are available for imported templates too, even if they are imported without
+context.  This is the place where you can put variables and functions
+that should be available all the time.  Additionally :attr:`Template.globals`
+exist that are variables available to a specific template that are available
+to all :meth:`~Template.render` calls.
+
+
+.. _low-level-api:
+
+Low Level API
+-------------
+
+The low level API exposes functionality that can be useful to understand some
+implementation details, debugging purposes or advanced :ref:`extension
+<jinja-extensions>` techniques.  Unless you know exactly what you are doing we
+don't recommend using any of those.
+
+.. automethod:: Environment.lex
+
+.. automethod:: Environment.parse
+
+.. automethod:: Environment.preprocess
+
+.. automethod:: Template.new_context
+
+.. method:: Template.root_render_func(context)
+
+    This is the low level render function.  It's passed a :class:`Context`
+    that has to be created by :meth:`new_context` of the same template or
+    a compatible template.  This render function is generated by the
+    compiler from the template code and returns a generator that yields
+    unicode strings.
+
+    If an exception in the template code happens the template engine will
+    not rewrite the exception but pass through the original one.  As a
+    matter of fact this function should only be called from within a
+    :meth:`render` / :meth:`generate` / :meth:`stream` call.
+
+.. attribute:: Template.blocks
+
+    A dict of block render functions.  Each of these functions works exactly
+    like the :meth:`root_render_func` with the same limitations.
+
+.. attribute:: Template.is_up_to_date
+
+    This attribute is `False` if there is a newer version of the template
+    available, otherwise `True`.
+
+.. admonition:: Note
+
+    The low-level API is fragile.  Future Jinja2 versions will try not to
+    change it in a backwards incompatible way but modifications in the Jinja2
+    core may shine through.  For example if Jinja2 introduces a new AST node
+    in later versions that may be returned by :meth:`~Environment.parse`.
+
+The Meta API
+------------
+
+.. versionadded:: 2.2
+
+The meta API returns some information about abstract syntax trees that
+could help applications to implement more advanced template concepts.  All
+the functions of the meta API operate on an abstract syntax tree as
+returned by the :meth:`Environment.parse` method.
+
+.. autofunction:: ambari_jinja2.meta.find_undeclared_variables
+
+.. autofunction:: ambari_jinja2.meta.find_referenced_templates

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py b/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py
new file mode 100644
index 0000000..d3703e3
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/cache_extension.py
@@ -0,0 +1,56 @@
+from ambari_jinja2 import nodes
+from ambari_jinja2.ext import Extension
+
+
+class FragmentCacheExtension(Extension):
+    # a set of names that trigger the extension.
+    tags = set(['cache'])
+
+    def __init__(self, environment):
+        super(FragmentCacheExtension, self).__init__(environment)
+
+        # add the defaults to the environment
+        environment.extend(
+            fragment_cache_prefix='',
+            fragment_cache=None
+        )
+
+    def parse(self, parser):
+        # the first token is the token that started the tag.  In our case
+        # we only listen to ``'cache'`` so this will be a name token with
+        # `cache` as value.  We get the line number so that we can give
+        # that line number to the nodes we create by hand.
+        lineno = parser.stream.next().lineno
+
+        # now we parse a single expression that is used as cache key.
+        args = [parser.parse_expression()]
+
+        # if there is a comma, the user provided a timeout.  If not use
+        # None as second parameter.
+        if parser.stream.skip_if('comma'):
+            args.append(parser.parse_expression())
+        else:
+            args.append(nodes.Const(None))
+
+        # now we parse the body of the cache block up to `endcache` and
+        # drop the needle (which would always be `endcache` in that case)
+        body = parser.parse_statements(['name:endcache'], drop_needle=True)
+
+        # now return a `CallBlock` node that calls our _cache_support
+        # helper method on this extension.
+        return nodes.CallBlock(self.call_method('_cache_support', args),
+                               [], [], body).set_lineno(lineno)
+
+    def _cache_support(self, name, timeout, caller):
+        """Helper callback."""
+        key = self.environment.fragment_cache_prefix + name
+
+        # try to load the block from the cache
+        # if there is no fragment in the cache, render it and store
+        # it in the cache.
+        rv = self.environment.fragment_cache.get(key)
+        if rv is not None:
+            return rv
+        rv = caller()
+        self.environment.fragment_cache.add(key, rv, timeout)
+        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst b/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst
new file mode 100644
index 0000000..6d6d6ca
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/changelog.rst
@@ -0,0 +1,3 @@
+.. module:: ambari_jinja2
+
+.. include:: ../CHANGES

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/conf.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/conf.py b/ambari-common/src/main/python/ambari_jinja2/docs/conf.py
new file mode 100644
index 0000000..ba90c49
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/conf.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+#
+# Jinja2 documentation build configuration file, created by
+# sphinx-quickstart on Sun Apr 27 21:42:41 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'jinjaext']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'Jinja2'
+copyright = '2008, Armin Ronacher'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '2.0'
+# The full version, including alpha/beta/rc tags.
+release = '2.0'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'jinjaext.JinjaStyle'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'style.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# no modindex
+html_use_modindex = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.
+#html_use_opensearch = False
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Jinja2doc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+latex_paper_size = 'a4'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'Jinja2.tex', 'Jinja2 Documentation', 'Armin Ronacher', 'manual', 'toctree_only'),
+]
+
+# Additional stuff for the LaTeX preamble.
+latex_preamble = '''
+\usepackage{palatino}
+\definecolor{TitleColor}{rgb}{0.7,0,0}
+\definecolor{InnerLinkColor}{rgb}{0.7,0,0}
+\definecolor{OuterLinkColor}{rgb}{0.8,0,0}
+\definecolor{VerbatimColor}{rgb}{0.985,0.985,0.985}
+\definecolor{VerbatimBorderColor}{rgb}{0.8,0.8,0.8}
+'''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+latex_use_modindex = False

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst b/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst
new file mode 100644
index 0000000..4d2c458
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/extensions.rst
@@ -0,0 +1,347 @@
+.. _jinja-extensions:
+
+Extensions
+==========
+
+Jinja2 supports extensions that can add extra filters, tests, globals or even
+extend the parser.  The main motivation of extensions is it to move often used
+code into a reusable class like adding support for internationalization.
+
+
+Adding Extensions
+-----------------
+
+Extensions are added to the Jinja2 environment at creation time.  Once the
+environment is created additional extensions cannot be added.  To add an
+extension pass a list of extension classes or import paths to the
+`environment` parameter of the :class:`Environment` constructor.  The following
+example creates a Jinja2 environment with the i18n extension loaded::
+
+    jinja_env = Environment(extensions=['ambari_jinja2.ext.i18n'])
+
+
+.. _i18n-extension:
+
+i18n Extension
+--------------
+
+**Import name:** `ambari_jinja2.ext.i18n`
+
+Jinja2 currently comes with one extension, the i18n extension.  It can be
+used in combination with `gettext`_ or `babel`_.  If the i18n extension is
+enabled Jinja2 provides a `trans` statement that marks the wrapped string as
+translatable and calls `gettext`.
+
+After enabling dummy `_` function that forwards calls to `gettext` is added
+to the environment globals.  An internationalized application then has to
+provide at least an `gettext` and optoinally a `ngettext` function into the
+namespace.  Either globally or for each rendering.
+
+Environment Methods
+~~~~~~~~~~~~~~~~~~~
+
+After enabling of the extension the environment provides the following
+additional methods:
+
+.. method:: ambari_jinja2.Environment.install_gettext_translations(translations, newstyle=False)
+
+    Installs a translation globally for that environment.  The tranlations
+    object provided must implement at least `ugettext` and `ungettext`.
+    The `gettext.NullTranslations` and `gettext.GNUTranslations` classes
+    as well as `Babel`_\s `Translations` class are supported.
+
+    .. versionchanged:: 2.5 newstyle gettext added
+
+.. method:: ambari_jinja2.Environment.install_null_translations(newstyle=False)
+
+    Install dummy gettext functions.  This is useful if you want to prepare
+    the application for internationalization but don't want to implement the
+    full internationalization system yet.
+
+    .. versionchanged:: 2.5 newstyle gettext added
+
+.. method:: ambari_jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False)
+
+    Installs the given `gettext` and `ngettext` callables into the
+    environment as globals.  They are supposed to behave exactly like the
+    standard library's :func:`gettext.ugettext` and
+    :func:`gettext.ungettext` functions.
+
+    If `newstyle` is activated, the callables are wrapped to work like
+    newstyle callables.  See :ref:`newstyle-gettext` for more information.
+
+    .. versionadded:: 2.5
+
+.. method:: ambari_jinja2.Environment.uninstall_gettext_translations()
+
+    Uninstall the translations again.
+
+.. method:: ambari_jinja2.Environment.extract_translations(source)
+
+    Extract localizable strings from the given template node or source.
+
+    For every string found this function yields a ``(lineno, function,
+    message)`` tuple, where:
+
+    * `lineno` is the number of the line on which the string was found,
+    * `function` is the name of the `gettext` function used (if the
+      string was extracted from embedded Python code), and
+    *  `message` is the string itself (a `unicode` object, or a tuple
+       of `unicode` objects for functions with multiple string arguments).
+
+    If `Babel`_ is installed :ref:`the babel integration <babel-integration>`
+    can be used to extract strings for babel.
+
+For a web application that is available in multiple languages but gives all
+the users the same language (for example a multilingual forum software
+installed for a French community) may load the translations once and add the
+translation methods to the environment at environment generation time::
+
+    translations = get_gettext_translations()
+    env = Environment(extensions=['ambari_jinja2.ext.i18n'])
+    env.install_gettext_translations(translations)
+
+The `get_gettext_translations` function would return the translator for the
+current configuration.  (For example by using `gettext.find`)
+
+The usage of the `i18n` extension for template designers is covered as part
+:ref:`of the template documentation <i18n-in-templates>`.
+
+.. _gettext: http://docs.python.org/dev/library/gettext
+.. _Babel: http://babel.edgewall.org/
+
+.. _newstyle-gettext:
+
+Newstyle Gettext
+~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.5
+
+Starting with version 2.5 you can use newstyle gettext calls.  These are
+inspired by trac's internal gettext functions and are fully supported by
+the babel extraction tool.  They might not work as expected by other
+extraction tools in case you are not using Babel's.
+
+What's the big difference between standard and newstyle gettext calls?  In
+general they are less to type and less error prone.  Also if they are used
+in an autoescaping environment they better support automatic escaping.
+Here some common differences between old and new calls:
+
+standard gettext:
+
+.. sourcecode:: html+jinja
+
+    {{ gettext('Hello World!') }}
+    {{ gettext('Hello %(name)s!')|format(name='World') }}
+    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count)|format(
+        num=apples|count
+    )}}
+
+newstyle gettext looks like this instead:
+
+.. sourcecode:: html+jinja
+
+    {{ gettext('Hello World!') }}
+    {{ gettext('Hello %(name)s!', name='World') }}
+    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
+
+The advantages of newstyle gettext is that you have less to type and that
+named placeholders become mandatory.  The latter sounds like a
+disadvantage but solves a lot of troubles translators are often facing
+when they are unable to switch the positions of two placeholder.  With
+newstyle gettext, all format strings look the same.
+
+Furthermore with newstyle gettext, string formatting is also used if no
+placeholders are used which makes all strings behave exactly the same.
+Last but not least are newstyle gettext calls able to properly mark
+strings for autoescaping which solves lots of escaping related issues many
+templates are experiencing over time when using autoescaping.
+
+Expression Statement
+--------------------
+
+**Import name:** `ambari_jinja2.ext.do`
+
+The "do" aka expression-statement extension adds a simple `do` tag to the
+template engine that works like a variable expression but ignores the
+return value.
+
+.. _loopcontrols-extension:
+
+Loop Controls
+-------------
+
+**Import name:** `ambari_jinja2.ext.loopcontrols`
+
+This extension adds support for `break` and `continue` in loops.  After
+enabling Jinja2 provides those two keywords which work exactly like in
+Python.
+
+.. _with-extension:
+
+With Statement
+--------------
+
+**Import name:** `ambari_jinja2.ext.with_`
+
+.. versionadded:: 2.3
+
+This extension adds support for the with keyword.  Using this keyword it
+is possible to enforce a nested scope in a template.  Variables can be
+declared directly in the opening block of the with statement or using a
+standard `set` statement directly within.
+
+.. _autoescape-extension:
+
+Autoescape Extension
+--------------------
+
+**Import name:** `ambari_jinja2.ext.autoescape`
+
+.. versionadded:: 2.4
+
+The autoescape extension allows you to toggle the autoescape feature from
+within the template.  If the environment's :attr:`~Environment.autoescape`
+setting is set to `False` it can be activated, if it's `True` it can be
+deactivated.  The setting overriding is scoped.
+
+
+.. _writing-extensions:
+
+Writing Extensions
+------------------
+
+.. module:: ambari_jinja2.ext
+
+By writing extensions you can add custom tags to Jinja2.  This is a non trival
+task and usually not needed as the default tags and expressions cover all
+common use cases.  The i18n extension is a good example of why extensions are
+useful, another one would be fragment caching.
+
+When writing extensions you have to keep in mind that you are working with the
+Jinja2 template compiler which does not validate the node tree you are possing
+to it.  If the AST is malformed you will get all kinds of compiler or runtime
+errors that are horrible to debug.  Always make sure you are using the nodes
+you create correctly.  The API documentation below shows which nodes exist and
+how to use them.
+
+Example Extension
+~~~~~~~~~~~~~~~~~
+
+The following example implements a `cache` tag for Jinja2 by using the
+`Werkzeug`_ caching contrib module:
+
+.. literalinclude:: cache_extension.py
+    :language: python
+
+And here is how you use it in an environment::
+
+    from ambari_jinja2 import Environment
+    from werkzeug.contrib.cache import SimpleCache
+
+    env = Environment(extensions=[FragmentCacheExtension])
+    env.fragment_cache = SimpleCache()
+
+Inside the template it's then possible to mark blocks as cacheable.  The
+following example caches a sidebar for 300 seconds:
+
+.. sourcecode:: html+jinja
+
+    {% cache 'sidebar', 300 %}
+    <div class="sidebar">
+        ...
+    </div>
+    {% endcache %}
+
+.. _Werkzeug: http://werkzeug.pocoo.org/
+
+Extension API
+~~~~~~~~~~~~~
+
+Extensions always have to extend the :class:`ambari_jinja2.ext.Extension` class:
+
+.. autoclass:: Extension
+    :members: preprocess, filter_stream, parse, attr, call_method
+
+    .. attribute:: identifier
+
+        The identifier of the extension.  This is always the true import name
+        of the extension class and must not be changed.
+
+    .. attribute:: tags
+
+        If the extension implements custom tags this is a set of tag names
+        the extension is listening for.
+
+Parser API
+~~~~~~~~~~
+
+The parser passed to :meth:`Extension.parse` provides ways to parse
+expressions of different types.  The following methods may be used by
+extensions:
+
+.. autoclass:: ambari_jinja2.parser.Parser
+    :members: parse_expression, parse_tuple, parse_assign_target,
+              parse_statements, free_identifier, fail
+
+    .. attribute:: filename
+
+        The filename of the template the parser processes.  This is **not**
+        the load name of the template.  For the load name see :attr:`name`.
+        For templates that were not loaded form the file system this is
+        `None`.
+
+    .. attribute:: name
+
+        The load name of the template.
+
+    .. attribute:: stream
+
+        The current :class:`~ambari_jinja2.lexer.TokenStream`
+
+.. autoclass:: ambari_jinja2.lexer.TokenStream
+   :members: push, look, eos, skip, next, next_if, skip_if, expect
+
+   .. attribute:: current
+
+        The current :class:`~ambari_jinja2.lexer.Token`.
+
+.. autoclass:: ambari_jinja2.lexer.Token
+    :members: test, test_any
+
+    .. attribute:: lineno
+
+        The line number of the token
+
+    .. attribute:: type
+
+        The type of the token.  This string is interned so you may compare
+        it with arbitrary strings using the `is` operator.
+
+    .. attribute:: value
+
+        The value of the token.
+
+There is also a utility function in the lexer module that can count newline
+characters in strings:
+
+.. autofunction:: ambari_jinja2.lexer.count_newlines
+
+AST
+~~~
+
+The AST (Abstract Syntax Tree) is used to represent a template after parsing.
+It's build of nodes that the compiler then converts into executable Python
+code objects.  Extensions that provide custom statements can return nodes to
+execute custom Python code.
+
+The list below describes all nodes that are currently available.  The AST may
+change between Jinja2 versions but will stay backwards compatible.
+
+For more information have a look at the repr of :meth:`ambari_jinja2.Environment.parse`.
+
+.. module:: ambari_jinja2.nodes
+
+.. jinjanodes::
+
+.. autoexception:: Impossible

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst b/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst
new file mode 100644
index 0000000..89186b1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/faq.rst
@@ -0,0 +1,191 @@
+Frequently Asked Questions
+==========================
+
+This page answers some of the often asked questions about Jinja.
+
+.. highlight:: html+jinja
+
+Why is it called Jinja?
+-----------------------
+
+The name Jinja was chosen because it's the name of a Japanese temple and
+temple and template share a similar pronunciation.  It is not named after
+the capital city of Uganda.
+
+How fast is it?
+---------------
+
+We really hate benchmarks especially since they don't reflect much.  The
+performance of a template depends on many factors and you would have to
+benchmark different engines in different situations.  The benchmarks from the
+testsuite show that Jinja2 has a similar performance to `Mako`_ and is between
+10 and 20 times faster than Django's template engine or Genshi.  These numbers
+should be taken with tons of salt as the benchmarks that took these numbers
+only test a few performance related situations such as looping.  Generally
+speaking the performance of a template engine doesn't matter much as the
+usual bottleneck in a web application is either the database or the application
+code.
+
+.. _Mako: http://www.makotemplates.org/
+
+How Compatible is Jinja2 with Django?
+-------------------------------------
+
+The default syntax of Jinja2 matches Django syntax in many ways.  However
+this similarity doesn't mean that you can use a Django template unmodified
+in Jinja2.  For example filter arguments use a function call syntax rather
+than a colon to separate filter name and arguments.  Additionally the
+extension interface in Jinja is fundamentally different from the Django one
+which means that your custom tags won't work any longer.
+
+Generally speaking you will use much less custom extensions as the Jinja
+template system allows you to use a certain subset of Python expressions
+which can replace most Django extensions.  For example instead of using
+something like this::
+
+    {% load comments %}
+    {% get_latest_comments 10 as latest_comments %}
+    {% for comment in latest_comments %}
+        ...
+    {% endfor %}
+
+You will most likely provide an object with attributes to retrieve
+comments from the database::
+
+    {% for comment in models.comments.latest(10) %}
+        ...
+    {% endfor %}
+
+Or directly provide the model for quick testing::
+
+    {% for comment in Comment.objects.order_by('-pub_date')[:10] %}
+        ...
+    {% endfor %}
+
+Please keep in mind that even though you may put such things into templates
+it still isn't a good idea.  Queries should go into the view code and not
+the template!
+
+Isn't it a terrible idea to put Logic into Templates?
+-----------------------------------------------------
+
+Without a doubt you should try to remove as much logic from templates as
+possible.  But templates without any logic mean that you have to do all
+the processing in the code which is boring and stupid.  A template engine
+that does that is shipped with Python and called `string.Template`.  Comes
+without loops and if conditions and is by far the fastest template engine
+you can get for Python.
+
+So some amount of logic is required in templates to keep everyone happy.
+And Jinja leaves it pretty much to you how much logic you want to put into
+templates.  There are some restrictions in what you can do and what not.
+
+Jinja2 neither allows you to put arbitrary Python code into templates nor
+does it allow all Python expressions.  The operators are limited to the
+most common ones and more advanced expressions such as list comprehensions
+and generator expressions are not supported.  This keeps the template engine
+easier to maintain and templates more readable.
+
+Why is Autoescaping not the Default?
+------------------------------------
+
+There are multiple reasons why automatic escaping is not the default mode
+and also not the recommended one.  While automatic escaping of variables
+means that you will less likely have an XSS problem it also causes a huge
+amount of extra processing in the template engine which can cause serious
+performance problems.  As Python doesn't provide a way to mark strings as
+unsafe Jinja has to hack around that limitation by providing a custom
+string class (the :class:`Markup` string) that safely interacts with safe
+and unsafe strings.
+
+With explicit escaping however the template engine doesn't have to perform
+any safety checks on variables.  Also a human knows not to escape integers
+or strings that may never contain characters one has to escape or already
+HTML markup.  For example when iterating over a list over a table of
+integers and floats for a table of statistics the template designer can
+omit the escaping because he knows that integers or floats don't contain
+any unsafe parameters.
+
+Additionally Jinja2 is a general purpose template engine and not only used
+for HTML/XML generation.  For example you may generate LaTeX, emails,
+CSS, JavaScript, or configuration files.
+
+Why is the Context immutable?
+-----------------------------
+
+When writing a :func:`contextfunction` or something similar you may have
+noticed that the context tries to stop you from modifying it.  If you have
+managed to modify the context by using an internal context API you may
+have noticed that changes in the context don't seem to be visible in the
+template.  The reason for this is that Jinja uses the context only as
+primary data source for template variables for performance reasons.
+
+If you want to modify the context write a function that returns a variable
+instead that one can assign to a variable by using set::
+
+    {% set comments = get_latest_comments() %}
+
+What is the speedups module and why is it missing?
+--------------------------------------------------
+
+To achieve a good performance with automatic escaping enabled, the escaping
+function was also implemented in pure C in older Jinja2 releases and used if
+Jinja2 was installed with the speedups module.
+
+Because this feature itself is very useful for non-template engines as
+well it was moved into a separate project on PyPI called `MarkupSafe`_.
+
+Jinja2 no longer ships with a C implementation of it but only the pure
+Python implementation.  It will however check if MarkupSafe is available
+and installed, and if it is, use the Markup class from MarkupSafe.
+
+So if you want the speedups, just import MarkupSafe.
+
+.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
+
+My tracebacks look weird.  What's happening?
+--------------------------------------------
+
+If the debugsupport module is not compiled and you are using a Python
+installation without ctypes (Python 2.4 without ctypes, Jython or Google's
+AppEngine) Jinja2 is unable to provide correct debugging information and
+the traceback may be incomplete.  There is currently no good workaround
+for Jython or the AppEngine as ctypes is unavailable there and it's not
+possible to use the debugsupport extension.
+
+Why is there no Python 2.3 support?
+-----------------------------------
+
+Python 2.3 is missing a lot of features that are used heavily in Jinja2.  This
+decision was made as with the upcoming Python 2.6 and 3.0 versions it becomes
+harder to maintain the code for older Python versions.  If you really need
+Python 2.3 support you either have to use `Jinja 1`_ or other templating
+engines that still support 2.3.
+
+My Macros are overriden by something
+------------------------------------
+
+In some situations the Jinja scoping appears arbitrary:
+
+layout.tmpl:
+
+.. sourcecode:: jinja
+
+    {% macro foo() %}LAYOUT{% endmacro %}
+    {% block body %}{% endblock %}
+
+child.tmpl:
+
+.. sourcecode:: jinja
+
+    {% extends 'layout.tmpl' %}
+    {% macro foo() %}CHILD{% endmacro %}
+    {% block body %}{{ foo() }}{% endblock %}
+
+This will print ``LAYOUT`` in Jinja2.  This is a side effect of having
+the parent template evaluated after the child one.  This allows child
+templates passing information to the parent template.  To avoid this
+issue rename the macro or variable in the parent template to have an
+uncommon prefix.
+
+.. _Jinja 1: http://jinja.pocoo.org/1/

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/index.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/index.rst b/ambari-common/src/main/python/ambari_jinja2/docs/index.rst
new file mode 100644
index 0000000..27bee23
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/index.rst
@@ -0,0 +1,27 @@
+Jinja2 Documentation
+====================
+
+This is the documentation for the Jinja2 general purpose templating language.
+Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
+fast and secure.
+
+.. toctree::
+   :maxdepth: 2
+
+   intro
+   api
+   sandbox
+   templates
+   extensions
+   integration
+   switching
+   tricks
+
+   faq
+   changelog
+
+If you can't find the information you're looking for, have a look at the
+index of try to find it using the search function:
+
+* :ref:`genindex`
+* :ref:`search`

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst b/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst
new file mode 100644
index 0000000..4f8614a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/docs/integration.rst
@@ -0,0 +1,88 @@
+Integration
+===========
+
+Jinja2 provides some code for integration into other tools such as frameworks,
+the `Babel`_ library or your favourite editor for fancy code highlighting.
+This is a brief description of whats included.
+
+.. _babel-integration:
+
+Babel Integration
+-----------------
+
+Jinja provides support for extracting gettext messages from templates via a
+`Babel`_ extractor entry point called `ambari_jinja2.ext.babel_extract`.  The Babel
+support is implemented as part of the :ref:`i18n-extension` extension.
+
+Gettext messages extracted from both `trans` tags and code expressions.
+
+To extract gettext messages from templates, the project needs a Jinja2 section
+in its Babel extraction method `mapping file`_:
+
+.. sourcecode:: ini
+
+    [ambari_jinja2: **/templates/**.html]
+    encoding = utf-8
+
+The syntax related options of the :class:`Environment` are also available as
+configuration values in the mapping file.  For example to tell the extraction
+that templates use ``%`` as `line_statement_prefix` you can use this code:
+
+.. sourcecode:: ini
+
+    [ambari_jinja2: **/templates/**.html]
+    encoding = utf-8
+    line_statement_prefix = %
+
+:ref:`jinja-extensions` may also be defined by passing a comma separated list
+of import paths as `extensions` value.  The i18n extension is added
+automatically.
+
+.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
+
+Pylons
+------
+
+With `Pylons`_ 0.9.7 onwards it's incredible easy to integrate Jinja into a
+Pylons powered application.
+
+The template engine is configured in `config/environment.py`.  The configuration
+for Jinja2 looks something like that::
+
+    from ambari_jinja2 import Environment, PackageLoader
+    config['pylons.app_globals'].jinja_env = Environment(
+        loader=PackageLoader('yourapplication', 'templates')
+    )
+
+After that you can render Jinja templates by using the `render_jinja` function
+from the `pylons.templating` module.
+
+Additionally it's a good idea to set the Pylons' `c` object into strict mode.
+Per default any attribute to not existing attributes on the `c` object return
+an empty string and not an undefined object.  To change this just use this
+snippet and add it into your `config/environment.py`::
+
+    config['pylons.strict_c'] = True
+
+.. _Pylons: http://www.pylonshq.com/
+
+TextMate
+--------
+
+Inside the `ext` folder of Jinja2 there is a bundle for TextMate that supports
+syntax highlighting for Jinja1 and Jinja2 for text based templates as well as
+HTML.  It also contains a few often used snippets.
+
+Vim
+---
+
+A syntax plugin for `Vim`_ exists in the Vim-scripts directory as well as the
+ext folder of Jinja2.  `The script <http://www.vim.org/scripts/script.php?script_id=1856>`_
+supports Jinja1 and Jinja2.  Once installed two file types are available `jinja`
+and `htmljinja`.  The first one for text based templates, the latter for HTML
+templates.
+
+Copy the files into your `syntax` folder.
+
+.. _Babel: http://babel.edgewall.org/
+.. _Vim: http://www.vim.org/


[02/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/sandbox.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/sandbox.py b/ambari-common/src/main/python/jinja2/jinja2/sandbox.py
new file mode 100644
index 0000000..7497195
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/sandbox.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.sandbox
+    ~~~~~~~~~~~~~~
+
+    Adds a sandbox layer to Jinja as it was the default behavior in the old
+    Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
+    default behavior is easier to use.
+
+    The behavior can be changed by subclassing the environment.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+import operator
+from jinja2.runtime import Undefined
+from jinja2.environment import Environment
+from jinja2.exceptions import SecurityError
+from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
+     FrameType, GeneratorType
+
+
+#: maximum number of items a range may produce
+MAX_RANGE = 100000
+
+#: attributes of function objects that are considered unsafe.
+UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
+                                  'func_defaults', 'func_globals'])
+
+#: unsafe method attributes.  function attributes are unsafe for methods too
+UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
+
+
+import warnings
+
+# make sure we don't warn in python 2.6 about stuff we don't care about
+warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
+                        module='jinja2.sandbox')
+
+from collections import deque
+
+_mutable_set_types = (set,)
+_mutable_mapping_types = (dict,)
+_mutable_sequence_types = (list,)
+
+
+# on python 2.x we can register the user collection types
+try:
+    from UserDict import UserDict, DictMixin
+    from UserList import UserList
+    _mutable_mapping_types += (UserDict, DictMixin)
+    _mutable_set_types += (UserList,)
+except ImportError:
+    pass
+
+# if sets is still available, register the mutable set from there as well
+try:
+    from sets import Set
+    _mutable_set_types += (Set,)
+except ImportError:
+    pass
+
+#: register Python 2.6 abstract base classes
+try:
+    from collections import MutableSet, MutableMapping, MutableSequence
+    _mutable_set_types += (MutableSet,)
+    _mutable_mapping_types += (MutableMapping,)
+    _mutable_sequence_types += (MutableSequence,)
+except ImportError:
+    pass
+
+_mutable_spec = (
+    (_mutable_set_types, frozenset([
+        'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
+        'symmetric_difference_update', 'update'
+    ])),
+    (_mutable_mapping_types, frozenset([
+        'clear', 'pop', 'popitem', 'setdefault', 'update'
+    ])),
+    (_mutable_sequence_types, frozenset([
+        'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
+    ])),
+    (deque, frozenset([
+        'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
+        'popleft', 'remove', 'rotate'
+    ]))
+)
+
+
+def safe_range(*args):
+    """A range that can't generate ranges with a length of more than
+    MAX_RANGE items.
+    """
+    rng = xrange(*args)
+    if len(rng) > MAX_RANGE:
+        raise OverflowError('range too big, maximum size for range is %d' %
+                            MAX_RANGE)
+    return rng
+
+
+def unsafe(f):
+    """
+    Mark a function or method as unsafe::
+
+        @unsafe
+        def delete(self):
+            pass
+    """
+    f.unsafe_callable = True
+    return f
+
+
+def is_internal_attribute(obj, attr):
+    """Test if the attribute given is an internal python attribute.  For
+    example this function returns `True` for the `func_code` attribute of
+    python objects.  This is useful if the environment method
+    :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
+
+    >>> from jinja2.sandbox import is_internal_attribute
+    >>> is_internal_attribute(lambda: None, "func_code")
+    True
+    >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
+    True
+    >>> is_internal_attribute(str, "upper")
+    False
+    """
+    if isinstance(obj, FunctionType):
+        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
+            return True
+    elif isinstance(obj, MethodType):
+        if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
+           attr in UNSAFE_METHOD_ATTRIBUTES:
+            return True
+    elif isinstance(obj, type):
+        if attr == 'mro':
+            return True
+    elif isinstance(obj, (CodeType, TracebackType, FrameType)):
+        return True
+    elif isinstance(obj, GeneratorType):
+        if attr == 'gi_frame':
+            return True
+    return attr.startswith('__')
+
+
+def modifies_known_mutable(obj, attr):
+    """This function checks if an attribute on a builtin mutable object
+    (list, dict, set or deque) would modify it if called.  It also supports
+    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
+    with Python 2.6 onwards the abstract base classes `MutableSet`,
+    `MutableMapping`, and `MutableSequence`.
+
+    >>> modifies_known_mutable({}, "clear")
+    True
+    >>> modifies_known_mutable({}, "keys")
+    False
+    >>> modifies_known_mutable([], "append")
+    True
+    >>> modifies_known_mutable([], "index")
+    False
+
+    If called with an unsupported object (such as unicode) `False` is
+    returned.
+
+    >>> modifies_known_mutable("foo", "upper")
+    False
+    """
+    for typespec, unsafe in _mutable_spec:
+        if isinstance(obj, typespec):
+            return attr in unsafe
+    return False
+
+
+class SandboxedEnvironment(Environment):
+    """The sandboxed environment.  It works like the regular environment but
+    tells the compiler to generate sandboxed code.  Additionally subclasses of
+    this environment may override the methods that tell the runtime what
+    attributes or functions are safe to access.
+
+    If the template tries to access insecure code a :exc:`SecurityError` is
+    raised.  However also other exceptions may occour during the rendering so
+    the caller has to ensure that all exceptions are catched.
+    """
+    sandboxed = True
+
+    def __init__(self, *args, **kwargs):
+        Environment.__init__(self, *args, **kwargs)
+        self.globals['range'] = safe_range
+
+    def is_safe_attribute(self, obj, attr, value):
+        """The sandboxed environment will call this method to check if the
+        attribute of an object is safe to access.  Per default all attributes
+        starting with an underscore are considered private as well as the
+        special attributes of internal python objects as returned by the
+        :func:`is_internal_attribute` function.
+        """
+        return not (attr.startswith('_') or is_internal_attribute(obj, attr))
+
+    def is_safe_callable(self, obj):
+        """Check if an object is safely callable.  Per default a function is
+        considered safe unless the `unsafe_callable` attribute exists and is
+        True.  Override this method to alter the behavior, but this won't
+        affect the `unsafe` decorator from this module.
+        """
+        return not (getattr(obj, 'unsafe_callable', False) or \
+                    getattr(obj, 'alters_data', False))
+
+    def getitem(self, obj, argument):
+        """Subscribe an object from sandboxed code."""
+        try:
+            return obj[argument]
+        except (TypeError, LookupError):
+            if isinstance(argument, basestring):
+                try:
+                    attr = str(argument)
+                except:
+                    pass
+                else:
+                    try:
+                        value = getattr(obj, attr)
+                    except AttributeError:
+                        pass
+                    else:
+                        if self.is_safe_attribute(obj, argument, value):
+                            return value
+                        return self.unsafe_undefined(obj, argument)
+        return self.undefined(obj=obj, name=argument)
+
+    def getattr(self, obj, attribute):
+        """Subscribe an object from sandboxed code and prefer the
+        attribute.  The attribute passed *must* be a bytestring.
+        """
+        try:
+            value = getattr(obj, attribute)
+        except AttributeError:
+            try:
+                return obj[attribute]
+            except (TypeError, LookupError):
+                pass
+        else:
+            if self.is_safe_attribute(obj, attribute, value):
+                return value
+            return self.unsafe_undefined(obj, attribute)
+        return self.undefined(obj=obj, name=attribute)
+
+    def unsafe_undefined(self, obj, attribute):
+        """Return an undefined object for unsafe attributes."""
+        return self.undefined('access to attribute %r of %r '
+                              'object is unsafe.' % (
+            attribute,
+            obj.__class__.__name__
+        ), name=attribute, obj=obj, exc=SecurityError)
+
+    def call(__self, __context, __obj, *args, **kwargs):
+        """Call an object from sandboxed code."""
+        # the double prefixes are to avoid double keyword argument
+        # errors when proxying the call.
+        if not __self.is_safe_callable(__obj):
+            raise SecurityError('%r is not safely callable' % (__obj,))
+        return __context.call(__obj, *args, **kwargs)
+
+
+class ImmutableSandboxedEnvironment(SandboxedEnvironment):
+    """Works exactly like the regular `SandboxedEnvironment` but does not
+    permit modifications on the builtin mutable objects `list`, `set`, and
+    `dict` by using the :func:`modifies_known_mutable` function.
+    """
+
+    def is_safe_attribute(self, obj, attr, value):
+        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
+            return False
+        return not modifies_known_mutable(obj, attr)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/tests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/tests.py b/ambari-common/src/main/python/jinja2/jinja2/tests.py
new file mode 100644
index 0000000..d257eca
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/tests.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.tests
+    ~~~~~~~~~~~~
+
+    Jinja test functions. Used with the "is" operator.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+from jinja2.runtime import Undefined
+
+# nose, nothing here to test
+__test__ = False
+
+
+number_re = re.compile(r'^-?\d+(\.\d+)?$')
+regex_type = type(number_re)
+
+
+try:
+    test_callable = callable
+except NameError:
+    def test_callable(x):
+        return hasattr(x, '__call__')
+
+
+def test_odd(value):
+    """Return true if the variable is odd."""
+    return value % 2 == 1
+
+
+def test_even(value):
+    """Return true if the variable is even."""
+    return value % 2 == 0
+
+
+def test_divisibleby(value, num):
+    """Check if a variable is divisible by a number."""
+    return value % num == 0
+
+
+def test_defined(value):
+    """Return true if the variable is defined:
+
+    .. sourcecode:: jinja
+
+        {% if variable is defined %}
+            value of variable: {{ variable }}
+        {% else %}
+            variable is not defined
+        {% endif %}
+
+    See the :func:`default` filter for a simple way to set undefined
+    variables.
+    """
+    return not isinstance(value, Undefined)
+
+
+def test_undefined(value):
+    """Like :func:`defined` but the other way round."""
+    return isinstance(value, Undefined)
+
+
+def test_none(value):
+    """Return true if the variable is none."""
+    return value is None
+
+
+def test_lower(value):
+    """Return true if the variable is lowercased."""
+    return unicode(value).islower()
+
+
+def test_upper(value):
+    """Return true if the variable is uppercased."""
+    return unicode(value).isupper()
+
+
+def test_string(value):
+    """Return true if the object is a string."""
+    return isinstance(value, basestring)
+
+
+def test_number(value):
+    """Return true if the variable is a number."""
+    return isinstance(value, (int, long, float, complex))
+
+
+def test_sequence(value):
+    """Return true if the variable is a sequence. Sequences are variables
+    that are iterable.
+    """
+    try:
+        len(value)
+        value.__getitem__
+    except:
+        return False
+    return True
+
+
+def test_sameas(value, other):
+    """Check if an object points to the same memory address than another
+    object:
+
+    .. sourcecode:: jinja
+
+        {% if foo.attribute is sameas false %}
+            the foo attribute really is the `False` singleton
+        {% endif %}
+    """
+    return value is other
+
+
+def test_iterable(value):
+    """Check if it's possible to iterate over an object."""
+    try:
+        iter(value)
+    except TypeError:
+        return False
+    return True
+
+
+def test_escaped(value):
+    """Check if the value is escaped."""
+    return hasattr(value, '__html__')
+
+
+TESTS = {
+    'odd':              test_odd,
+    'even':             test_even,
+    'divisibleby':      test_divisibleby,
+    'defined':          test_defined,
+    'undefined':        test_undefined,
+    'none':             test_none,
+    'lower':            test_lower,
+    'upper':            test_upper,
+    'string':           test_string,
+    'number':           test_number,
+    'sequence':         test_sequence,
+    'iterable':         test_iterable,
+    'callable':         test_callable,
+    'sameas':           test_sameas,
+    'escaped':          test_escaped
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py
new file mode 100644
index 0000000..1f10ef6
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/__init__.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite
+    ~~~~~~~~~~~~~~~~
+
+    All the unittests of Jinja2.  These tests can be executed by
+    either running run-tests.py using multiple Python versions at
+    the same time.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import re
+import sys
+import unittest
+from traceback import format_exception
+from jinja2 import loaders
+
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+dict_loader = loaders.DictLoader({
+    'justdict.html':        'FOO'
+})
+package_loader = loaders.PackageLoader('jinja2.testsuite.res', 'templates')
+filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
+function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
+choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
+prefix_loader = loaders.PrefixLoader({
+    'a':        filesystem_loader,
+    'b':        dict_loader
+})
+
+
+class JinjaTestCase(unittest.TestCase):
+
+    ### use only these methods for testing.  If you need standard
+    ### unittest method, wrap them!
+
+    def setup(self):
+        pass
+
+    def teardown(self):
+        pass
+
+    def setUp(self):
+        self.setup()
+
+    def tearDown(self):
+        self.teardown()
+
+    def assert_equal(self, a, b):
+        return self.assertEqual(a, b)
+
+    def assert_raises(self, *args, **kwargs):
+        return self.assertRaises(*args, **kwargs)
+
+    def assert_traceback_matches(self, callback, expected_tb):
+        try:
+            callback()
+        except Exception, e:
+            tb = format_exception(*sys.exc_info())
+            if re.search(expected_tb.strip(), ''.join(tb)) is None:
+                raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
+                    % (''.join(tb), expected_tb))
+        else:
+            self.fail('Expected exception')
+
+
+def suite():
+    from jinja2.testsuite import ext, filters, tests, core_tags, \
+         loader, inheritance, imports, lexnparse, security, api, \
+         regression, debug, utils, doctests
+    suite = unittest.TestSuite()
+    suite.addTest(ext.suite())
+    suite.addTest(filters.suite())
+    suite.addTest(tests.suite())
+    suite.addTest(core_tags.suite())
+    suite.addTest(loader.suite())
+    suite.addTest(inheritance.suite())
+    suite.addTest(imports.suite())
+    suite.addTest(lexnparse.suite())
+    suite.addTest(security.suite())
+    suite.addTest(api.suite())
+    suite.addTest(regression.suite())
+    suite.addTest(debug.suite())
+    suite.addTest(utils.suite())
+
+    # doctests will not run on python 3 currently.  Too many issues
+    # with that, do not test that on that platform.
+    if sys.version_info < (3, 0):
+        suite.addTest(doctests.suite())
+
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py
new file mode 100644
index 0000000..7463c7f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/api.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.api
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Tests the public API and related stuff.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, Undefined, DebugUndefined, \
+     StrictUndefined, UndefinedError, Template, meta, \
+     is_undefined, Template, DictLoader
+from jinja2.utils import Cycler
+
+env = Environment()
+
+
+class ExtendedAPITestCase(JinjaTestCase):
+
+    def test_item_and_attribute(self):
+        from jinja2.sandbox import SandboxedEnvironment
+
+        for env in Environment(), SandboxedEnvironment():
+            # the |list is necessary for python3
+            tmpl = env.from_string('{{ foo.items()|list }}')
+            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+            tmpl = env.from_string('{{ foo|attr("items")()|list }}')
+            assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+            tmpl = env.from_string('{{ foo["items"] }}')
+            assert tmpl.render(foo={'items': 42}) == '42'
+
+    def test_finalizer(self):
+        def finalize_none_empty(value):
+            if value is None:
+                value = u''
+            return value
+        env = Environment(finalize=finalize_none_empty)
+        tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
+        assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo'
+        tmpl = env.from_string('<{{ none }}>')
+        assert tmpl.render() == '<>'
+
+    def test_cycler(self):
+        items = 1, 2, 3
+        c = Cycler(*items)
+        for item in items + items:
+            assert c.current == item
+            assert c.next() == item
+        c.next()
+        assert c.current == 2
+        c.reset()
+        assert c.current == 1
+
+    def test_expressions(self):
+        expr = env.compile_expression("foo")
+        assert expr() is None
+        assert expr(foo=42) == 42
+        expr2 = env.compile_expression("foo", undefined_to_none=False)
+        assert is_undefined(expr2())
+
+        expr = env.compile_expression("42 + foo")
+        assert expr(foo=42) == 84
+
+    def test_template_passthrough(self):
+        t = Template('Content')
+        assert env.get_template(t) is t
+        assert env.select_template([t]) is t
+        assert env.get_or_select_template([t]) is t
+        assert env.get_or_select_template(t) is t
+
+    def test_autoescape_autoselect(self):
+        def select_autoescape(name):
+            if name is None or '.' not in name:
+                return False
+            return name.endswith('.html')
+        env = Environment(autoescape=select_autoescape,
+                          loader=DictLoader({
+            'test.txt':     '{{ foo }}',
+            'test.html':    '{{ foo }}'
+        }))
+        t = env.get_template('test.txt')
+        assert t.render(foo='<foo>') == '<foo>'
+        t = env.get_template('test.html')
+        assert t.render(foo='<foo>') == '&lt;foo&gt;'
+        t = env.from_string('{{ foo }}')
+        assert t.render(foo='<foo>') == '<foo>'
+
+
+class MetaTestCase(JinjaTestCase):
+
+    def test_find_undeclared_variables(self):
+        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+        x = meta.find_undeclared_variables(ast)
+        assert x == set(['bar'])
+
+        ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
+                        '{% macro meh(x) %}{{ x }}{% endmacro %}'
+                        '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
+        x = meta.find_undeclared_variables(ast)
+        assert x == set(['bar', 'seq', 'muh'])
+
+    def test_find_refererenced_templates(self):
+        ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+        i = meta.find_referenced_templates(ast)
+        assert i.next() == 'layout.html'
+        assert i.next() is None
+        assert list(i) == []
+
+        ast = env.parse('{% extends "layout.html" %}'
+                        '{% from "test.html" import a, b as c %}'
+                        '{% import "meh.html" as meh %}'
+                        '{% include "muh.html" %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
+
+    def test_find_included_templates(self):
+        ast = env.parse('{% include ["foo.html", "bar.html"] %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html']
+
+        ast = env.parse('{% include ("foo.html", "bar.html") %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html']
+
+        ast = env.parse('{% include ["foo.html", "bar.html", foo] %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html', None]
+
+        ast = env.parse('{% include ("foo.html", "bar.html", foo) %}')
+        i = meta.find_referenced_templates(ast)
+        assert list(i) == ['foo.html', 'bar.html', None]
+
+
+class StreamingTestCase(JinjaTestCase):
+
+    def test_basic_streaming(self):
+        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+                               "}} - {{ item }}</li>{%- endfor %}</ul>")
+        stream = tmpl.stream(seq=range(4))
+        self.assert_equal(stream.next(), '<ul>')
+        self.assert_equal(stream.next(), '<li>1 - 0</li>')
+        self.assert_equal(stream.next(), '<li>2 - 1</li>')
+        self.assert_equal(stream.next(), '<li>3 - 2</li>')
+        self.assert_equal(stream.next(), '<li>4 - 3</li>')
+        self.assert_equal(stream.next(), '</ul>')
+
+    def test_buffered_streaming(self):
+        tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+                               "}} - {{ item }}</li>{%- endfor %}</ul>")
+        stream = tmpl.stream(seq=range(4))
+        stream.enable_buffering(size=3)
+        self.assert_equal(stream.next(), u'<ul><li>1 - 0</li><li>2 - 1</li>')
+        self.assert_equal(stream.next(), u'<li>3 - 2</li><li>4 - 3</li></ul>')
+
+    def test_streaming_behavior(self):
+        tmpl = env.from_string("")
+        stream = tmpl.stream()
+        assert not stream.buffered
+        stream.enable_buffering(20)
+        assert stream.buffered
+        stream.disable_buffering()
+        assert not stream.buffered
+
+
+class UndefinedTestCase(JinjaTestCase):
+
+    def test_stopiteration_is_undefined(self):
+        def test():
+            raise StopIteration()
+        t = Template('A{{ test() }}B')
+        assert t.render(test=test) == 'AB'
+        t = Template('A{{ test().missingattribute }}B')
+        self.assert_raises(UndefinedError, t.render, test=test)
+
+    def test_default_undefined(self):
+        env = Environment(undefined=Undefined)
+        self.assert_equal(env.from_string('{{ missing }}').render(), u'')
+        self.assert_raises(UndefinedError,
+                           env.from_string('{{ missing.attribute }}').render)
+        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
+        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
+        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
+
+    def test_debug_undefined(self):
+        env = Environment(undefined=DebugUndefined)
+        self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
+        self.assert_raises(UndefinedError,
+                           env.from_string('{{ missing.attribute }}').render)
+        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
+        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
+                          u"{{ no such element: int object['missing'] }}")
+        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
+
+    def test_strict_undefined(self):
+        env = Environment(undefined=StrictUndefined)
+        self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
+        self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
+        self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
+        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+        self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
+        self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
+
+    def test_indexing_gives_undefined(self):
+        t = Template("{{ var[42].foo }}")
+        self.assert_raises(UndefinedError, t.render, var=0)
+
+    def test_none_gives_proper_error(self):
+        try:
+            Environment().getattr(None, 'split')()
+        except UndefinedError, e:
+            assert e.message == "'None' has no attribute 'split'"
+        else:
+            assert False, 'expected exception'
+
+    def test_object_repr(self):
+        try:
+            Undefined(obj=42, name='upper')()
+        except UndefinedError, e:
+            assert e.message == "'int object' has no attribute 'upper'"
+        else:
+            assert False, 'expected exception'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
+    suite.addTest(unittest.makeSuite(MetaTestCase))
+    suite.addTest(unittest.makeSuite(StreamingTestCase))
+    suite.addTest(unittest.makeSuite(UndefinedTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py
new file mode 100644
index 0000000..d456b4f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/core_tags.py
@@ -0,0 +1,286 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.core_tags
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test the core tags like for and if.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
+     DictLoader
+
+env = Environment()
+
+
+class ForLoopTestCase(JinjaTestCase):
+
+    def test_simple(self):
+        tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
+        assert tmpl.render(seq=range(10)) == '0123456789'
+
+    def test_else(self):
+        tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
+        assert tmpl.render() == '...'
+
+    def test_empty_blocks(self):
+        tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
+        assert tmpl.render() == '<>'
+
+    def test_context_vars(self):
+        tmpl = env.from_string('''{% for item in seq -%}
+        {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
+            loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
+           loop.length }}###{% endfor %}''')
+        one, two, _ = tmpl.render(seq=[0, 1]).split('###')
+        (one_index, one_index0, one_revindex, one_revindex0, one_first,
+         one_last, one_length) = one.split('|')
+        (two_index, two_index0, two_revindex, two_revindex0, two_first,
+         two_last, two_length) = two.split('|')
+
+        assert int(one_index) == 1 and int(two_index) == 2
+        assert int(one_index0) == 0 and int(two_index0) == 1
+        assert int(one_revindex) == 2 and int(two_revindex) == 1
+        assert int(one_revindex0) == 1 and int(two_revindex0) == 0
+        assert one_first == 'True' and two_first == 'False'
+        assert one_last == 'False' and two_last == 'True'
+        assert one_length == two_length == '2'
+
+    def test_cycling(self):
+        tmpl = env.from_string('''{% for item in seq %}{{
+            loop.cycle('<1>', '<2>') }}{% endfor %}{%
+            for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
+        output = tmpl.render(seq=range(4), through=('<1>', '<2>'))
+        assert output == '<1><2>' * 4
+
+    def test_scope(self):
+        tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
+        output = tmpl.render(seq=range(10))
+        assert not output
+
+    def test_varlen(self):
+        def inner():
+            for item in range(5):
+                yield item
+        tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}')
+        output = tmpl.render(iter=inner())
+        assert output == '01234'
+
+    def test_noniter(self):
+        tmpl = env.from_string('{% for item in none %}...{% endfor %}')
+        self.assert_raises(TypeError, tmpl.render)
+
+    def test_recursive(self):
+        tmpl = env.from_string('''{% for item in seq recursive -%}
+            [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+        {%- endfor %}''')
+        assert tmpl.render(seq=[
+            dict(a=1, b=[dict(a=1), dict(a=2)]),
+            dict(a=2, b=[dict(a=1), dict(a=2)]),
+            dict(a=3, b=[dict(a='a')])
+        ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
+
+    def test_looploop(self):
+        tmpl = env.from_string('''{% for row in table %}
+            {%- set rowloop = loop -%}
+            {% for cell in row -%}
+                [{{ rowloop.index }}|{{ loop.index }}]
+            {%- endfor %}
+        {%- endfor %}''')
+        assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
+
+    def test_reversed_bug(self):
+        tmpl = env.from_string('{% for i in items %}{{ i }}'
+                               '{% if not loop.last %}'
+                               ',{% endif %}{% endfor %}')
+        assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
+
+    def test_loop_errors(self):
+        tmpl = env.from_string('''{% for item in [1] if loop.index
+                                      == 0 %}...{% endfor %}''')
+        self.assert_raises(UndefinedError, tmpl.render)
+        tmpl = env.from_string('''{% for item in [] %}...{% else
+            %}{{ loop }}{% endfor %}''')
+        assert tmpl.render() == ''
+
+    def test_loop_filter(self):
+        tmpl = env.from_string('{% for item in range(10) if item '
+                               'is even %}[{{ item }}]{% endfor %}')
+        assert tmpl.render() == '[0][2][4][6][8]'
+        tmpl = env.from_string('''
+            {%- for item in range(10) if item is even %}[{{
+                loop.index }}:{{ item }}]{% endfor %}''')
+        assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
+
+    def test_loop_unassignable(self):
+        self.assert_raises(TemplateSyntaxError, env.from_string,
+                           '{% for loop in seq %}...{% endfor %}')
+
+    def test_scoped_special_var(self):
+        t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
+                            '|{{ loop.first }}{% endfor %}]{% endfor %}')
+        assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
+
+    def test_scoped_loop_var(self):
+        t = env.from_string('{% for x in seq %}{{ loop.first }}'
+                            '{% for y in seq %}{% endfor %}{% endfor %}')
+        assert t.render(seq='ab') == 'TrueFalse'
+        t = env.from_string('{% for x in seq %}{% for y in seq %}'
+                            '{{ loop.first }}{% endfor %}{% endfor %}')
+        assert t.render(seq='ab') == 'TrueFalseTrueFalse'
+
+    def test_recursive_empty_loop_iter(self):
+        t = env.from_string('''
+        {%- for item in foo recursive -%}{%- endfor -%}
+        ''')
+        assert t.render(dict(foo=[])) == ''
+
+    def test_call_in_loop(self):
+        t = env.from_string('''
+        {%- macro do_something() -%}
+            [{{ caller() }}]
+        {%- endmacro %}
+
+        {%- for i in [1, 2, 3] %}
+            {%- call do_something() -%}
+                {{ i }}
+            {%- endcall %}
+        {%- endfor -%}
+        ''')
+        assert t.render() == '[1][2][3]'
+
+    def test_scoping_bug(self):
+        t = env.from_string('''
+        {%- for item in foo %}...{{ item }}...{% endfor %}
+        {%- macro item(a) %}...{{ a }}...{% endmacro %}
+        {{- item(2) -}}
+        ''')
+        assert t.render(foo=(1,)) == '...1......2...'
+
+    def test_unpacking(self):
+        tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
+            '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
+        assert tmpl.render() == '1|2|3'
+
+
+class IfConditionTestCase(JinjaTestCase):
+
+    def test_simple(self):
+        tmpl = env.from_string('''{% if true %}...{% endif %}''')
+        assert tmpl.render() == '...'
+
+    def test_elif(self):
+        tmpl = env.from_string('''{% if false %}XXX{% elif true
+            %}...{% else %}XXX{% endif %}''')
+        assert tmpl.render() == '...'
+
+    def test_else(self):
+        tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
+        assert tmpl.render() == '...'
+
+    def test_empty(self):
+        tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
+        assert tmpl.render() == '[]'
+
+    def test_complete(self):
+        tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
+                               'C{% else %}D{% endif %}')
+        assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
+
+    def test_no_scope(self):
+        tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
+        assert tmpl.render(a=True) == '1'
+        tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
+        assert tmpl.render() == '1'
+
+
+class MacrosTestCase(JinjaTestCase):
+    env = Environment(trim_blocks=True)
+
+    def test_simple(self):
+        tmpl = self.env.from_string('''\
+{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
+{{ say_hello('Peter') }}''')
+        assert tmpl.render() == 'Hello Peter!'
+
+    def test_scoping(self):
+        tmpl = self.env.from_string('''\
+{% macro level1(data1) %}
+{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
+{{ level2('bar') }}{% endmacro %}
+{{ level1('foo') }}''')
+        assert tmpl.render() == 'foo|bar'
+
+    def test_arguments(self):
+        tmpl = self.env.from_string('''\
+{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
+{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
+        assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
+
+    def test_varargs(self):
+        tmpl = self.env.from_string('''\
+{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
+{{ test(1, 2, 3) }}''')
+        assert tmpl.render() == '1|2|3'
+
+    def test_simple_call(self):
+        tmpl = self.env.from_string('''\
+{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
+{% call test() %}data{% endcall %}''')
+        assert tmpl.render() == '[[data]]'
+
+    def test_complex_call(self):
+        tmpl = self.env.from_string('''\
+{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
+{% call(data) test() %}{{ data }}{% endcall %}''')
+        assert tmpl.render() == '[[data]]'
+
+    def test_caller_undefined(self):
+        tmpl = self.env.from_string('''\
+{% set caller = 42 %}\
+{% macro test() %}{{ caller is not defined }}{% endmacro %}\
+{{ test() }}''')
+        assert tmpl.render() == 'True'
+
+    def test_include(self):
+        self.env = Environment(loader=DictLoader({'include':
+            '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
+        tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
+        assert tmpl.render() == '[foo]'
+
+    def test_macro_api(self):
+        tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
+                               '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
+                               '{% macro baz() %}{{ caller() }}{% endmacro %}')
+        assert tmpl.module.foo.arguments == ('a', 'b')
+        assert tmpl.module.foo.defaults == ()
+        assert tmpl.module.foo.name == 'foo'
+        assert not tmpl.module.foo.caller
+        assert not tmpl.module.foo.catch_kwargs
+        assert not tmpl.module.foo.catch_varargs
+        assert tmpl.module.bar.arguments == ()
+        assert tmpl.module.bar.defaults == ()
+        assert not tmpl.module.bar.caller
+        assert tmpl.module.bar.catch_kwargs
+        assert tmpl.module.bar.catch_varargs
+        assert tmpl.module.baz.caller
+
+    def test_callself(self):
+        tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
+                                    '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
+                                    '{{ foo(5) }}')
+        assert tmpl.render() == '5|4|3|2|1'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ForLoopTestCase))
+    suite.addTest(unittest.makeSuite(IfConditionTestCase))
+    suite.addTest(unittest.makeSuite(MacrosTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py
new file mode 100644
index 0000000..7552dec
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/debug.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.debug
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests the debug system.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import sys
+import unittest
+
+from jinja2.testsuite import JinjaTestCase, filesystem_loader
+
+from jinja2 import Environment, TemplateSyntaxError
+
+env = Environment(loader=filesystem_loader)
+
+
+class DebugTestCase(JinjaTestCase):
+
+    if sys.version_info[:2] != (2, 4):
+        def test_runtime_error(self):
+            def test():
+                tmpl.render(fail=lambda: 1 / 0)
+            tmpl = env.get_template('broken.html')
+            self.assert_traceback_matches(test, r'''
+  File ".*?broken.html", line 2, in (top-level template code|<module>)
+    \{\{ fail\(\) \}\}
+  File ".*?debug.pyc?", line \d+, in <lambda>
+    tmpl\.render\(fail=lambda: 1 / 0\)
+ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
+''')
+
+    def test_syntax_error(self):
+        # XXX: the .*? is necessary for python3 which does not hide
+        # some of the stack frames we don't want to show.  Not sure
+        # what's up with that, but that is not that critical.  Should
+        # be fixed though.
+        self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
+  File ".*?syntaxerror.html", line 4, in (template|<module>)
+    \{% endif %\}.*?
+(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
+    ''')
+
+    def test_regular_syntax_error(self):
+        def test():
+            raise TemplateSyntaxError('wtf', 42)
+        self.assert_traceback_matches(test, r'''
+  File ".*debug.pyc?", line \d+, in test
+    raise TemplateSyntaxError\('wtf', 42\)
+(jinja2\.exceptions\.)?TemplateSyntaxError: wtf
+  line 42''')
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(DebugTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py
new file mode 100644
index 0000000..616d3b6
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/doctests.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.doctests
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    The doctests.  Collects all tests we want to test from
+    the Jinja modules.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import unittest
+import doctest
+
+
+def suite():
+    from jinja2 import utils, sandbox, runtime, meta, loaders, \
+        ext, environment, bccache, nodes
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocTestSuite(utils))
+    suite.addTest(doctest.DocTestSuite(sandbox))
+    suite.addTest(doctest.DocTestSuite(runtime))
+    suite.addTest(doctest.DocTestSuite(meta))
+    suite.addTest(doctest.DocTestSuite(loaders))
+    suite.addTest(doctest.DocTestSuite(ext))
+    suite.addTest(doctest.DocTestSuite(environment))
+    suite.addTest(doctest.DocTestSuite(bccache))
+    suite.addTest(doctest.DocTestSuite(nodes))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py
new file mode 100644
index 0000000..89b8579
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/ext.py
@@ -0,0 +1,455 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.ext
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Tests for the extensions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import re
+import unittest
+
+from jinja2.testsuite import JinjaTestCase, filesystem_loader
+
+from jinja2 import Environment, DictLoader, contextfunction, nodes
+from jinja2.exceptions import TemplateAssertionError
+from jinja2.ext import Extension
+from jinja2.lexer import Token, count_newlines
+from jinja2.utils import next
+
+# 2.x / 3.x
+try:
+    from io import BytesIO
+except ImportError:
+    from StringIO import StringIO as BytesIO
+
+
+importable_object = 23
+
+_gettext_re = re.compile(r'_\((.*?)\)(?s)')
+
+
+i18n_templates = {
+    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+                   '{% block body %}{% endblock %}',
+    'child.html': '{% extends "master.html" %}{% block body %}'
+                  '{% trans %}watch out{% endtrans %}{% endblock %}',
+    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+                   '{{ user_count }} users online{% endtrans %}',
+    'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}'
+}
+
+newstyle_i18n_templates = {
+    'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+                   '{% block body %}{% endblock %}',
+    'child.html': '{% extends "master.html" %}{% block body %}'
+                  '{% trans %}watch out{% endtrans %}{% endblock %}',
+    'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+                   '{{ user_count }} users online{% endtrans %}',
+    'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}',
+    'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}',
+    'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}'
+                          '{{ num }} apples{% endtrans %}',
+    'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}',
+    'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}',
+    'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}',
+    'novars.html': '{% trans %}%(hello)s{% endtrans %}',
+    'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}',
+    'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}'
+}
+
+
+languages = {
+    'de': {
+        'missing':                      u'fehlend',
+        'watch out':                    u'pass auf',
+        'One user online':              u'Ein Benutzer online',
+        '%(user_count)s users online':  u'%(user_count)s Benutzer online',
+        'User: %(num)s':                u'Benutzer: %(num)s',
+        'User: %(count)s':              u'Benutzer: %(count)s',
+        '%(num)s apple':                u'%(num)s Apfel',
+        '%(num)s apples':               u'%(num)s Äpfel'
+    }
+}
+
+
+@contextfunction
+def gettext(context, string):
+    language = context.get('LANGUAGE', 'en')
+    return languages.get(language, {}).get(string, string)
+
+
+@contextfunction
+def ngettext(context, s, p, n):
+    language = context.get('LANGUAGE', 'en')
+    if n != 1:
+        return languages.get(language, {}).get(p, p)
+    return languages.get(language, {}).get(s, s)
+
+
+i18n_env = Environment(
+    loader=DictLoader(i18n_templates),
+    extensions=['jinja2.ext.i18n']
+)
+i18n_env.globals.update({
+    '_':            gettext,
+    'gettext':      gettext,
+    'ngettext':     ngettext
+})
+
+newstyle_i18n_env = Environment(
+    loader=DictLoader(newstyle_i18n_templates),
+    extensions=['jinja2.ext.i18n']
+)
+newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
+
+class TestExtension(Extension):
+    tags = set(['test'])
+    ext_attr = 42
+
+    def parse(self, parser):
+        return nodes.Output([self.call_method('_dump', [
+            nodes.EnvironmentAttribute('sandboxed'),
+            self.attr('ext_attr'),
+            nodes.ImportedName(__name__ + '.importable_object'),
+            nodes.ContextReference()
+        ])]).set_lineno(next(parser.stream).lineno)
+
+    def _dump(self, sandboxed, ext_attr, imported_object, context):
+        return '%s|%s|%s|%s' % (
+            sandboxed,
+            ext_attr,
+            imported_object,
+            context.blocks
+        )
+
+
+class PreprocessorExtension(Extension):
+
+    def preprocess(self, source, name, filename=None):
+        return source.replace('[[TEST]]', '({{ foo }})')
+
+
+class StreamFilterExtension(Extension):
+
+    def filter_stream(self, stream):
+        for token in stream:
+            if token.type == 'data':
+                for t in self.interpolate(token):
+                    yield t
+            else:
+                yield token
+
+    def interpolate(self, token):
+        pos = 0
+        end = len(token.value)
+        lineno = token.lineno
+        while 1:
+            match = _gettext_re.search(token.value, pos)
+            if match is None:
+                break
+            value = token.value[pos:match.start()]
+            if value:
+                yield Token(lineno, 'data', value)
+            lineno += count_newlines(token.value)
+            yield Token(lineno, 'variable_begin', None)
+            yield Token(lineno, 'name', 'gettext')
+            yield Token(lineno, 'lparen', None)
+            yield Token(lineno, 'string', match.group(1))
+            yield Token(lineno, 'rparen', None)
+            yield Token(lineno, 'variable_end', None)
+            pos = match.end()
+        if pos < end:
+            yield Token(lineno, 'data', token.value[pos:])
+
+
+class ExtensionsTestCase(JinjaTestCase):
+
+    def test_extend_late(self):
+        env = Environment()
+        env.add_extension('jinja2.ext.autoescape')
+        t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
+        assert t.render() == '&lt;test&gt;'
+
+    def test_loop_controls(self):
+        env = Environment(extensions=['jinja2.ext.loopcontrols'])
+
+        tmpl = env.from_string('''
+            {%- for item in [1, 2, 3, 4] %}
+                {%- if item % 2 == 0 %}{% continue %}{% endif -%}
+                {{ item }}
+            {%- endfor %}''')
+        assert tmpl.render() == '13'
+
+        tmpl = env.from_string('''
+            {%- for item in [1, 2, 3, 4] %}
+                {%- if item > 2 %}{% break %}{% endif -%}
+                {{ item }}
+            {%- endfor %}''')
+        assert tmpl.render() == '12'
+
+    def test_do(self):
+        env = Environment(extensions=['jinja2.ext.do'])
+        tmpl = env.from_string('''
+            {%- set items = [] %}
+            {%- for char in "foo" %}
+                {%- do items.append(loop.index0 ~ char) %}
+            {%- endfor %}{{ items|join(', ') }}''')
+        assert tmpl.render() == '0f, 1o, 2o'
+
+    def test_with(self):
+        env = Environment(extensions=['jinja2.ext.with_'])
+        tmpl = env.from_string('''\
+        {% with a=42, b=23 -%}
+            {{ a }} = {{ b }}
+        {% endwith -%}
+            {{ a }} = {{ b }}\
+        ''')
+        assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
+            == ['42 = 23', '1 = 2']
+
+    def test_extension_nodes(self):
+        env = Environment(extensions=[TestExtension])
+        tmpl = env.from_string('{% test %}')
+        assert tmpl.render() == 'False|42|23|{}'
+
+    def test_identifier(self):
+        assert TestExtension.identifier == __name__ + '.TestExtension'
+
+    def test_rebinding(self):
+        original = Environment(extensions=[TestExtension])
+        overlay = original.overlay()
+        for env in original, overlay:
+            for ext in env.extensions.itervalues():
+                assert ext.environment is env
+
+    def test_preprocessor_extension(self):
+        env = Environment(extensions=[PreprocessorExtension])
+        tmpl = env.from_string('{[[TEST]]}')
+        assert tmpl.render(foo=42) == '{(42)}'
+
+    def test_streamfilter_extension(self):
+        env = Environment(extensions=[StreamFilterExtension])
+        env.globals['gettext'] = lambda x: x.upper()
+        tmpl = env.from_string('Foo _(bar) Baz')
+        out = tmpl.render()
+        assert out == 'Foo BAR Baz'
+
+    def test_extension_ordering(self):
+        class T1(Extension):
+            priority = 1
+        class T2(Extension):
+            priority = 2
+        env = Environment(extensions=[T1, T2])
+        ext = list(env.iter_extensions())
+        assert ext[0].__class__ is T1
+        assert ext[1].__class__ is T2
+
+
+class InternationalizationTestCase(JinjaTestCase):
+
+    def test_trans(self):
+        tmpl = i18n_env.get_template('child.html')
+        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+    def test_trans_plural(self):
+        tmpl = i18n_env.get_template('plural.html')
+        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+    def test_complex_plural(self):
+        tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
+                                    'pluralize count %}{{ count }} items{% endtrans %}')
+        assert tmpl.render() == '2 items'
+        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
+                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+    def test_trans_stringformatting(self):
+        tmpl = i18n_env.get_template('stringformat.html')
+        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+    def test_extract(self):
+        from jinja2.ext import babel_extract
+        source = BytesIO('''
+        {{ gettext('Hello World') }}
+        {% trans %}Hello World{% endtrans %}
+        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+        '''.encode('ascii')) # make python 3 happy
+        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
+            (2, 'gettext', u'Hello World', []),
+            (3, 'gettext', u'Hello World', []),
+            (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
+        ]
+
+    def test_comment_extract(self):
+        from jinja2.ext import babel_extract
+        source = BytesIO('''
+        {# trans first #}
+        {{ gettext('Hello World') }}
+        {% trans %}Hello World{% endtrans %}{# trans second #}
+        {#: third #}
+        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+        '''.encode('utf-8')) # make python 3 happy
+        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
+            (3, 'gettext', u'Hello World', ['first']),
+            (4, 'gettext', u'Hello World', ['second']),
+            (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
+        ]
+
+
+class NewstyleInternationalizationTestCase(JinjaTestCase):
+
+    def test_trans(self):
+        tmpl = newstyle_i18n_env.get_template('child.html')
+        assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+    def test_trans_plural(self):
+        tmpl = newstyle_i18n_env.get_template('plural.html')
+        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+        assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+    def test_complex_plural(self):
+        tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
+                                    'pluralize count %}{{ count }} items{% endtrans %}')
+        assert tmpl.render() == '2 items'
+        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
+                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+    def test_trans_stringformatting(self):
+        tmpl = newstyle_i18n_env.get_template('stringformat.html')
+        assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+    def test_newstyle_plural(self):
+        tmpl = newstyle_i18n_env.get_template('ngettext.html')
+        assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel'
+        assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel'
+
+    def test_autoescape_support(self):
+        env = Environment(extensions=['jinja2.ext.autoescape',
+                                      'jinja2.ext.i18n'])
+        env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
+                                      lambda s, p, n: s, newstyle=True)
+        t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
+                            '"<test>") }}{% endautoescape %}')
+        assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
+        assert t.render(ae=False) == '<strong>Wert: <test></strong>'
+
+    def test_num_used_twice(self):
+        tmpl = newstyle_i18n_env.get_template('ngettext_long.html')
+        assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Äpfel'
+
+    def test_num_called_num(self):
+        source = newstyle_i18n_env.compile('''
+            {% trans num=3 %}{{ num }} apple{% pluralize
+            %}{{ num }} apples{% endtrans %}
+        ''', raw=True)
+        # quite hacky, but the only way to properly test that.  The idea is
+        # that the generated code does not pass num twice (although that
+        # would work) for better performance.  This only works on the
+        # newstyle gettext of course
+        assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s "
+                         r"apples', 3", source) is not None
+
+    def test_trans_vars(self):
+        t1 = newstyle_i18n_env.get_template('transvars1.html')
+        t2 = newstyle_i18n_env.get_template('transvars2.html')
+        t3 = newstyle_i18n_env.get_template('transvars3.html')
+        assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1'
+        assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23'
+        assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42'
+
+    def test_novars_vars_escaping(self):
+        t = newstyle_i18n_env.get_template('novars.html')
+        assert t.render() == '%(hello)s'
+        t = newstyle_i18n_env.get_template('vars.html')
+        assert t.render(foo='42') == '42%(foo)s'
+        t = newstyle_i18n_env.get_template('explicitvars.html')
+        assert t.render() == '%(foo)s'
+
+
+class AutoEscapeTestCase(JinjaTestCase):
+
+    def test_scoped_setting(self):
+        env = Environment(extensions=['jinja2.ext.autoescape'],
+                          autoescape=True)
+        tmpl = env.from_string('''
+            {{ "<HelloWorld>" }}
+            {% autoescape false %}
+                {{ "<HelloWorld>" }}
+            {% endautoescape %}
+            {{ "<HelloWorld>" }}
+        ''')
+        assert tmpl.render().split() == \
+            [u'&lt;HelloWorld&gt;', u'<HelloWorld>', u'&lt;HelloWorld&gt;']
+
+        env = Environment(extensions=['jinja2.ext.autoescape'],
+                          autoescape=False)
+        tmpl = env.from_string('''
+            {{ "<HelloWorld>" }}
+            {% autoescape true %}
+                {{ "<HelloWorld>" }}
+            {% endautoescape %}
+            {{ "<HelloWorld>" }}
+        ''')
+        assert tmpl.render().split() == \
+            [u'<HelloWorld>', u'&lt;HelloWorld&gt;', u'<HelloWorld>']
+
+    def test_nonvolatile(self):
+        env = Environment(extensions=['jinja2.ext.autoescape'],
+                          autoescape=True)
+        tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}')
+        assert tmpl.render() == ' foo="&lt;test&gt;"'
+        tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}'
+                               '|xmlattr|escape }}{% endautoescape %}')
+        assert tmpl.render() == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+
+    def test_volatile(self):
+        env = Environment(extensions=['jinja2.ext.autoescape'],
+                          autoescape=True)
+        tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}'
+                               '|xmlattr|escape }}{% endautoescape %}')
+        assert tmpl.render(foo=False) == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+        assert tmpl.render(foo=True) == ' foo="&lt;test&gt;"'
+
+    def test_scoping(self):
+        env = Environment(extensions=['jinja2.ext.autoescape'])
+        tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
+                               '{% endautoescape %}{{ x }}{{ "<y>" }}')
+        assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
+
+    def test_volatile_scoping(self):
+        env = Environment(extensions=['jinja2.ext.autoescape'])
+        tmplsource = '''
+        {% autoescape val %}
+            {% macro foo(x) %}
+                [{{ x }}]
+            {% endmacro %}
+            {{ foo().__class__.__name__ }}
+        {% endautoescape %}
+        {{ '<testing>' }}
+        '''
+        tmpl = env.from_string(tmplsource)
+        assert tmpl.render(val=True).split()[0] == 'Markup'
+        assert tmpl.render(val=False).split()[0] == unicode.__name__
+
+        # looking at the source we should see <testing> there in raw
+        # (and then escaped as well)
+        env = Environment(extensions=['jinja2.ext.autoescape'])
+        pysource = env.compile(tmplsource, raw=True)
+        assert '<testing>\\n' in pysource
+
+        env = Environment(extensions=['jinja2.ext.autoescape'],
+                          autoescape=True)
+        pysource = env.compile(tmplsource, raw=True)
+        assert '&lt;testing&gt;\\n' in pysource
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ExtensionsTestCase))
+    suite.addTest(unittest.makeSuite(InternationalizationTestCase))
+    suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
+    suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py
new file mode 100644
index 0000000..b59c9e3
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/filters.py
@@ -0,0 +1,291 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.filters
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests for the jinja filters.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import unittest
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Markup, Environment
+
+env = Environment()
+
+
+class FilterTestCase(JinjaTestCase):
+
+    def test_capitalize(self):
+        tmpl = env.from_string('{{ "foo bar"|capitalize }}')
+        assert tmpl.render() == 'Foo bar'
+
+    def test_center(self):
+        tmpl = env.from_string('{{ "foo"|center(9) }}')
+        assert tmpl.render() == '   foo   '
+
+    def test_default(self):
+        tmpl = env.from_string(
+            "{{ missing|default('no') }}|{{ false|default('no') }}|"
+            "{{ false|default('no', true) }}|{{ given|default('no') }}"
+        )
+        assert tmpl.render(given='yes') == 'no|False|no|yes'
+
+    def test_dictsort(self):
+        tmpl = env.from_string(
+            '{{ foo|dictsort }}|'
+            '{{ foo|dictsort(true) }}|'
+            '{{ foo|dictsort(false, "value") }}'
+        )
+        out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
+        assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
+                       "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
+                       "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
+
+    def test_batch(self):
+        tmpl = env.from_string("{{ foo|batch(3)|list }}|"
+                               "{{ foo|batch(3, 'X')|list }}")
+        out = tmpl.render(foo=range(10))
+        assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
+                       "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
+
+    def test_slice(self):
+        tmpl = env.from_string('{{ foo|slice(3)|list }}|'
+                               '{{ foo|slice(3, "X")|list }}')
+        out = tmpl.render(foo=range(10))
+        assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
+                       "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
+
+    def test_escape(self):
+        tmpl = env.from_string('''{{ '<">&'|escape }}''')
+        out = tmpl.render()
+        assert out == '&lt;&#34;&gt;&amp;'
+
+    def test_striptags(self):
+        tmpl = env.from_string('''{{ foo|striptags }}''')
+        out = tmpl.render(foo='  <p>just a small   \n <a href="#">'
+                          'example</a> link</p>\n<p>to a webpage</p> '
+                          '<!-- <p>and some commented stuff</p> -->')
+        assert out == 'just a small example link to a webpage'
+
+    def test_filesizeformat(self):
+        tmpl = env.from_string(
+            '{{ 100|filesizeformat }}|'
+            '{{ 1000|filesizeformat }}|'
+            '{{ 1000000|filesizeformat }}|'
+            '{{ 1000000000|filesizeformat }}|'
+            '{{ 1000000000000|filesizeformat }}|'
+            '{{ 100|filesizeformat(true) }}|'
+            '{{ 1000|filesizeformat(true) }}|'
+            '{{ 1000000|filesizeformat(true) }}|'
+            '{{ 1000000000|filesizeformat(true) }}|'
+            '{{ 1000000000000|filesizeformat(true) }}'
+        )
+        out = tmpl.render()
+        assert out == (
+            '100 Bytes|1.0 KB|1.0 MB|1.0 GB|1000.0 GB|'
+            '100 Bytes|1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
+        )
+
+    def test_first(self):
+        tmpl = env.from_string('{{ foo|first }}')
+        out = tmpl.render(foo=range(10))
+        assert out == '0'
+
+    def test_float(self):
+        tmpl = env.from_string('{{ "42"|float }}|'
+                               '{{ "ajsghasjgd"|float }}|'
+                               '{{ "32.32"|float }}')
+        out = tmpl.render()
+        assert out == '42.0|0.0|32.32'
+
+    def test_format(self):
+        tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
+        out = tmpl.render()
+        assert out == 'a|b'
+
+    def test_indent(self):
+        tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
+        text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
+        out = tmpl.render(foo=text)
+        assert out == ('foo bar foo bar\n  foo bar foo bar|  '
+                       'foo bar foo bar\n  foo bar foo bar')
+
+    def test_int(self):
+        tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
+                               '{{ "32.32"|int }}')
+        out = tmpl.render()
+        assert out == '42|0|32'
+
+    def test_join(self):
+        tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
+        out = tmpl.render()
+        assert out == '1|2|3'
+
+        env2 = Environment(autoescape=True)
+        tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
+        assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
+
+    def test_last(self):
+        tmpl = env.from_string('''{{ foo|last }}''')
+        out = tmpl.render(foo=range(10))
+        assert out == '9'
+
+    def test_length(self):
+        tmpl = env.from_string('''{{ "hello world"|length }}''')
+        out = tmpl.render()
+        assert out == '11'
+
+    def test_lower(self):
+        tmpl = env.from_string('''{{ "FOO"|lower }}''')
+        out = tmpl.render()
+        assert out == 'foo'
+
+    def test_pprint(self):
+        from pprint import pformat
+        tmpl = env.from_string('''{{ data|pprint }}''')
+        data = range(1000)
+        assert tmpl.render(data=data) == pformat(data)
+
+    def test_random(self):
+        tmpl = env.from_string('''{{ seq|random }}''')
+        seq = range(100)
+        for _ in range(10):
+            assert int(tmpl.render(seq=seq)) in seq
+
+    def test_reverse(self):
+        tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
+                               '{{ [1, 2, 3]|reverse|list }}')
+        assert tmpl.render() == 'raboof|[3, 2, 1]'
+
+    def test_string(self):
+        x = [1, 2, 3, 4, 5]
+        tmpl = env.from_string('''{{ obj|string }}''')
+        assert tmpl.render(obj=x) == unicode(x)
+
+    def test_title(self):
+        tmpl = env.from_string('''{{ "foo bar"|title }}''')
+        assert tmpl.render() == "Foo Bar"
+
+    def test_truncate(self):
+        tmpl = env.from_string(
+            '{{ data|truncate(15, true, ">>>") }}|'
+            '{{ data|truncate(15, false, ">>>") }}|'
+            '{{ smalldata|truncate(15) }}'
+        )
+        out = tmpl.render(data='foobar baz bar' * 1000,
+                          smalldata='foobar baz bar')
+        assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar'
+
+    def test_upper(self):
+        tmpl = env.from_string('{{ "foo"|upper }}')
+        assert tmpl.render() == 'FOO'
+
+    def test_urlize(self):
+        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
+        assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
+                                'http://www.example.com/</a> bar'
+
+    def test_wordcount(self):
+        tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
+        assert tmpl.render() == '3'
+
+    def test_block(self):
+        tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
+        assert tmpl.render() == '&lt;hehe&gt;'
+
+    def test_chaining(self):
+        tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
+        assert tmpl.render() == '&lt;FOO&gt;'
+
+    def test_sum(self):
+        tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
+        assert tmpl.render() == '21'
+
+    def test_abs(self):
+        tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
+        assert tmpl.render() == '1|1', tmpl.render()
+
+    def test_round_positive(self):
+        tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
+                               "{{ 2.1234|round(3, 'floor') }}|"
+                               "{{ 2.1|round(0, 'ceil') }}")
+        assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
+
+    def test_round_negative(self):
+        tmpl = env.from_string('{{ 21.3|round(-1)}}|'
+                               "{{ 21.3|round(-1, 'ceil')}}|"
+                               "{{ 21.3|round(-1, 'floor')}}")
+        assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
+
+    def test_xmlattr(self):
+        tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
+                               "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
+        out = tmpl.render().split()
+        assert len(out) == 3
+        assert 'foo="42"' in out
+        assert 'bar="23"' in out
+        assert 'blub:blub="&lt;?&gt;"' in out
+
+    def test_sort1(self):
+        tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
+        assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+    def test_sort2(self):
+        tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort(false, true)) }}')
+        assert tmpl.render() == 'AbcD'
+
+    def test_groupby(self):
+        tmpl = env.from_string('''
+        {%- for grouper, list in [{'foo': 1, 'bar': 2},
+                                  {'foo': 2, 'bar': 3},
+                                  {'foo': 1, 'bar': 1},
+                                  {'foo': 3, 'bar': 4}]|groupby('foo') -%}
+            {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
+        {%- endfor %}''')
+        assert tmpl.render().split('|') == [
+            "1: 1, 2: 1, 1",
+            "2: 2, 3",
+            "3: 3, 4",
+            ""
+        ]
+
+    def test_filtertag(self):
+        tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
+                               "foobar{% endfilter %}")
+        assert tmpl.render() == 'fooBAR'
+
+    def test_replace(self):
+        env = Environment()
+        tmpl = env.from_string('{{ string|replace("o", 42) }}')
+        assert tmpl.render(string='<foo>') == '<f4242>'
+        env = Environment(autoescape=True)
+        tmpl = env.from_string('{{ string|replace("o", 42) }}')
+        assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
+        tmpl = env.from_string('{{ string|replace("<", 42) }}')
+        assert tmpl.render(string='<foo>') == '42foo&gt;'
+        tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
+        assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
+
+    def test_forceescape(self):
+        tmpl = env.from_string('{{ x|forceescape }}')
+        assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
+
+    def test_safe(self):
+        env = Environment(autoescape=True)
+        tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
+        assert tmpl.render() == '<div>foo</div>'
+        tmpl = env.from_string('{{ "<div>foo</div>" }}')
+        assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
+
+    def test_sort2(self):
+        tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
+        assert tmpl.render() == "['Bar', 'blah', 'foo']"
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(FilterTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py
new file mode 100644
index 0000000..c785606
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/imports.py
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.imports
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests the import features (with includes).
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, DictLoader
+from jinja2.exceptions import TemplateNotFound, TemplatesNotFound
+
+
+test_env = Environment(loader=DictLoader(dict(
+    module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
+    header='[{{ foo }}|{{ 23 }}]',
+    o_printer='({{ o }})'
+)))
+test_env.globals['bar'] = 23
+
+
+class ImportsTestCase(JinjaTestCase):
+
+    def test_context_imports(self):
+        t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
+        assert t.render(foo=42) == '[42|23]'
+        t = test_env.from_string('{% from "module" import test %}{{ test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
+        assert t.render(foo=42) == '[|23]'
+        t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
+        assert t.render(foo=42) == '[42|23]'
+
+    def test_trailing_comma(self):
+        test_env.from_string('{% from "foo" import bar, baz with context %}')
+        test_env.from_string('{% from "foo" import bar, baz, with context %}')
+        test_env.from_string('{% from "foo" import bar, with context %}')
+        test_env.from_string('{% from "foo" import bar, with, context %}')
+        test_env.from_string('{% from "foo" import bar, with with context %}')
+
+    def test_exports(self):
+        m = test_env.from_string('''
+            {% macro toplevel() %}...{% endmacro %}
+            {% macro __private() %}...{% endmacro %}
+            {% set variable = 42 %}
+            {% for item in [1] %}
+                {% macro notthere() %}{% endmacro %}
+            {% endfor %}
+        ''').module
+        assert m.toplevel() == '...'
+        assert not hasattr(m, '__missing')
+        assert m.variable == 42
+        assert not hasattr(m, 'notthere')
+
+
+class IncludesTestCase(JinjaTestCase):
+
+    def test_context_include(self):
+        t = test_env.from_string('{% include "header" %}')
+        assert t.render(foo=42) == '[42|23]'
+        t = test_env.from_string('{% include "header" with context %}')
+        assert t.render(foo=42) == '[42|23]'
+        t = test_env.from_string('{% include "header" without context %}')
+        assert t.render(foo=42) == '[|23]'
+
+    def test_choice_includes(self):
+        t = test_env.from_string('{% include ["missing", "header"] %}')
+        assert t.render(foo=42) == '[42|23]'
+
+        t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
+        assert t.render(foo=42) == ''
+
+        t = test_env.from_string('{% include ["missing", "missing2"] %}')
+        self.assert_raises(TemplateNotFound, t.render)
+        try:
+            t.render()
+        except TemplatesNotFound, e:
+            assert e.templates == ['missing', 'missing2']
+            assert e.name == 'missing2'
+        else:
+            assert False, 'thou shalt raise'
+
+        def test_includes(t, **ctx):
+            ctx['foo'] = 42
+            assert t.render(ctx) == '[42|23]'
+
+        t = test_env.from_string('{% include ["missing", "header"] %}')
+        test_includes(t)
+        t = test_env.from_string('{% include x %}')
+        test_includes(t, x=['missing', 'header'])
+        t = test_env.from_string('{% include [x, "header"] %}')
+        test_includes(t, x='missing')
+        t = test_env.from_string('{% include x %}')
+        test_includes(t, x='header')
+        t = test_env.from_string('{% include x %}')
+        test_includes(t, x='header')
+        t = test_env.from_string('{% include [x] %}')
+        test_includes(t, x='header')
+
+    def test_include_ignoring_missing(self):
+        t = test_env.from_string('{% include "missing" %}')
+        self.assert_raises(TemplateNotFound, t.render)
+        for extra in '', 'with context', 'without context':
+            t = test_env.from_string('{% include "missing" ignore missing ' +
+                                     extra + ' %}')
+            assert t.render() == ''
+
+    def test_context_include_with_overrides(self):
+        env = Environment(loader=DictLoader(dict(
+            main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
+            item="{{ item }}"
+        )))
+        assert env.get_template("main").render() == "123"
+
+    def test_unoptimized_scopes(self):
+        t = test_env.from_string("""
+            {% macro outer(o) %}
+            {% macro inner() %}
+            {% include "o_printer" %}
+            {% endmacro %}
+            {{ inner() }}
+            {% endmacro %}
+            {{ outer("FOO") }}
+        """)
+        assert t.render().strip() == '(FOO)'
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ImportsTestCase))
+    suite.addTest(unittest.makeSuite(IncludesTestCase))
+    return suite

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py b/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py
new file mode 100644
index 0000000..87b4a59
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/jinja2/testsuite/inheritance.py
@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.inheritance
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Tests the template inheritance feature.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import time
+import tempfile
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, DictLoader
+from jinja2.exceptions import TemplateSyntaxError
+
+
+LAYOUTTEMPLATE = '''\
+|{% block block1 %}block 1 from layout{% endblock %}
+|{% block block2 %}block 2 from layout{% endblock %}
+|{% block block3 %}
+{% block block4 %}nested block 4 from layout{% endblock %}
+{% endblock %}|'''
+
+LEVEL1TEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}block 1 from level1{% endblock %}'''
+
+LEVEL2TEMPLATE = '''\
+{% extends "level1" %}
+{% block block2 %}{% block block5 %}nested block 5 from level2{%
+endblock %}{% endblock %}'''
+
+LEVEL3TEMPLATE = '''\
+{% extends "level2" %}
+{% block block5 %}block 5 from level3{% endblock %}
+{% block block4 %}block 4 from level3{% endblock %}
+'''
+
+LEVEL4TEMPLATE = '''\
+{% extends "level3" %}
+{% block block3 %}block 3 from level4{% endblock %}
+'''
+
+WORKINGTEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}
+  {% if false %}
+    {% block block2 %}
+      this should workd
+    {% endblock %}
+  {% endif %}
+{% endblock %}
+'''
+
+env = Environment(loader=DictLoader({
+    'layout':       LAYOUTTEMPLATE,
+    'level1':       LEVEL1TEMPLATE,
+    'level2':       LEVEL2TEMPLATE,
+    'level3':       LEVEL3TEMPLATE,
+    'level4':       LEVEL4TEMPLATE,
+    'working':      WORKINGTEMPLATE
+}), trim_blocks=True)
+
+
+class InheritanceTestCase(JinjaTestCase):
+
+    def test_layout(self):
+        tmpl = env.get_template('layout')
+        assert tmpl.render() == ('|block 1 from layout|block 2 from '
+                                 'layout|nested block 4 from layout|')
+
+    def test_level1(self):
+        tmpl = env.get_template('level1')
+        assert tmpl.render() == ('|block 1 from level1|block 2 from '
+                                 'layout|nested block 4 from layout|')
+
+    def test_level2(self):
+        tmpl = env.get_template('level2')
+        assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
+                                 'level2|nested block 4 from layout|')
+
+    def test_level3(self):
+        tmpl = env.get_template('level3')
+        assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
+                                 'block 4 from level3|')
+
+    def test_level4(sel):
+        tmpl = env.get_template('level4')
+        assert tmpl.render() == ('|block 1 from level1|block 5 from '
+                                 'level3|block 3 from level4|')
+
+    def test_super(self):
+        env = Environment(loader=DictLoader({
+            'a': '{% block intro %}INTRO{% endblock %}|'
+                 'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
+            'b': '{% extends "a" %}{% block data %}({{ '
+                 'super() }}){% endblock %}',
+            'c': '{% extends "b" %}{% block intro %}--{{ '
+                 'super() }}--{% endblock %}\n{% block data '
+                 '%}[{{ super() }}]{% endblock %}'
+        }))
+        tmpl = env.get_template('c')
+        assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
+
+    def test_working(self):
+        tmpl = env.get_template('working')
+
+    def test_reuse_blocks(self):
+        tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
+                               '{% endblock %}|{{ self.foo() }}')
+        assert tmpl.render() == '42|42|42'
+
+    def test_preserve_blocks(self):
+        env = Environment(loader=DictLoader({
+            'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
+            'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
+        }))
+        tmpl = env.get_template('b')
+        assert tmpl.render() == 'BA'
+
+    def test_dynamic_inheritance(self):
+        env = Environment(loader=DictLoader({
+            'master1': 'MASTER1{% block x %}{% endblock %}',
+            'master2': 'MASTER2{% block x %}{% endblock %}',
+            'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
+        }))
+        tmpl = env.get_template('child')
+        for m in range(1, 3):
+            assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
+
+    def test_multi_inheritance(self):
+        env = Environment(loader=DictLoader({
+            'master1': 'MASTER1{% block x %}{% endblock %}',
+            'master2': 'MASTER2{% block x %}{% endblock %}',
+            'child': '''{% if master %}{% extends master %}{% else %}{% extends
+                        'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
+        }))
+        tmpl = env.get_template('child')
+        assert tmpl.render(master='master2') == 'MASTER2CHILD'
+        assert tmpl.render(master='master1') == 'MASTER1CHILD'
+        assert tmpl.render() == 'MASTER1CHILD'
+
+    def test_scoped_block(self):
+        env = Environment(loader=DictLoader({
+            'master.html': '{% for item in seq %}[{% block item scoped %}'
+                           '{% endblock %}]{% endfor %}'
+        }))
+        t = env.from_string('{% extends "master.html" %}{% block item %}'
+                            '{{ item }}{% endblock %}')
+        assert t.render(seq=range(5)) == '[0][1][2][3][4]'
+
+    def test_super_in_scoped_block(self):
+        env = Environment(loader=DictLoader({
+            'master.html': '{% for item in seq %}[{% block item scoped %}'
+                           '{{ item }}{% endblock %}]{% endfor %}'
+        }))
+        t = env.from_string('{% extends "master.html" %}{% block item %}'
+                            '{{ super() }}|{{ item * 2 }}{% endblock %}')
+        assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]'
+
+
+class BugFixTestCase(JinjaTestCase):
+
+    def test_fixed_macro_scoping_bug(self):
+        assert Environment(loader=DictLoader({
+            'test.html': '''\
+        {% extends 'details.html' %}
+
+        {% macro my_macro() %}
+        my_macro
+        {% endmacro %}
+
+        {% block inner_box %}
+            {{ my_macro() }}
+        {% endblock %}
+            ''',
+            'details.html': '''\
+        {% extends 'standard.html' %}
+
+        {% macro my_macro() %}
+        my_macro
+        {% endmacro %}
+
+        {% block content %}
+            {% block outer_box %}
+                outer_box
+                {% block inner_box %}
+                    inner_box
+                {% endblock %}
+            {% endblock %}
+        {% endblock %}
+        ''',
+            'standard.html': '''
+        {% block content %}&nbsp;{% endblock %}
+        '''
+        })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(InheritanceTestCase))
+    suite.addTest(unittest.makeSuite(BugFixTestCase))
+    return suite


[21/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py
deleted file mode 100644
index 83d1528..0000000
--- a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/_stringdefs.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ambari_jinja2._stringdefs
-    ~~~~~~~~~~~~~~~~~~
-
-    Strings of all Unicode characters of a certain category.
-    Used for matching in Unicode-aware languages. Run to regenerate.
-
-    Inspired by chartypes_create.py from the MoinMoin project, original
-    implementation from Pygments.
-
-    :copyright: Copyright 2006-2009 by the Jinja team, see AUTHORS.
-    :license: BSD, see LICENSE for details.
-"""
-
-Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
-
-Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb'
-
-Cn = u'\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0370\u0371\u0372\u0373\u0376\u0377\u0378\u0379\u037b\u037c\u037d\u037f\u0380\u0381\u0382\u0383\u038b\u038d\u03a2\u03cf\u0487\u04cf\u04fa\u04fb\u04fc\u04fd\u04fe\u04ff\u0510\u0511\u0512\u0513\u0514\u0515\u0516\u0517\u0518\u0519\u051a\u051b\u051c\u051d\u051e\u051f\u0520\u0521\u0522\u0523\u0524\u0525\u0526\u0527\u0528\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0557\u0558\u0560\u0588\u058b\u058c\u058d\u058e\u058f\u0590\u05ba\u05c8\u05c9\u05ca\u05cb\u05cc\u05cd\u05ce\u05cf\u05eb\u05ec\u05ed\u05ee\u05ef\u05f5\u05f6\u05f7\u05f8\u05f9\u05fa\u05fb\u05fc\u05fd\u05fe\u05ff\u0604\u0605\u0606\u0607\u0608\u0609\u060a\u0616\u0617\u0618\u0619\u061a\u061c\u061d\u0620\u063b\u063c\u063d\u063e\u063f\u065f\u070e\u074b\u074c\u076e\u076f\u0770\u0771\u0772\u0773\u0774\u0775\u0776\u0777\u0778\u0779\u077a\u077b\u077c\u077d\u077e\u077f\u07b2\u07b3\u07b4\u07b5\u07b6\u07b7\u07b8\u07b9\u07ba\u07bb\u07bc\u07bd\u07be
 \u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u07c7\u07c8\u07c9\u07ca\u07cb\u07cc\u07cd\u07ce\u07cf\u07d0\u07d1\u07d2\u07d3\u07d4\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07db\u07dc\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3\u07e4\u07e5\u07e6\u07e7\u07e8\u07e9\u07ea\u07eb\u07ec\u07ed\u07ee\u07ef\u07f0\u07f1\u07f2\u07f3\u07f4\u07f5\u07f6\u07f7\u07f8\u07f9\u07fa\u07fb\u07fc\u07fd\u07fe\u07ff\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u0817\u0818\u0819\u081a\u081b\u081c\u081d\u081e\u081f\u0820\u0821\u0822\u0823\u0824\u0825\u0826\u0827\u0828\u0829\u082a\u082b\u082c\u082d\u082e\u082f\u0830\u0831\u0832\u0833\u0834\u0835\u0836\u0837\u0838\u0839\u083a\u083b\u083c\u083d\u083e\u083f\u0840\u0841\u0842\u0843\u0844\u0845\u0846\u0847\u0848\u0849\u084a\u084b\u084c\u084d\u084e\u084f\u0850\u0851\u0852\u0853\u0854\u0855\u0856\u0857\u0858\u0859\u085a\u085b\u085c\u085d\u085e\u085f\u0860\u0861\u0862\u0863\u0864\
 u0865\u0866\u0867\u0868\u0869\u086a\u086b\u086c\u086d\u086e\u086f\u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087a\u087b\u087c\u087d\u087e\u087f\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0888\u0889\u088a\u088b\u088c\u088d\u088e\u088f\u0890\u0891\u0892\u0893\u0894\u0895\u0896\u0897\u0898\u0899\u089a\u089b\u089c\u089d\u089e\u089f\u08a0\u08a1\u08a2\u08a3\u08a4\u08a5\u08a6\u08a7\u08a8\u08a9\u08aa\u08ab\u08ac\u08ad\u08ae\u08af\u08b0\u08b1\u08b2\u08b3\u08b4\u08b5\u08b6\u08b7\u08b8\u08b9\u08ba\u08bb\u08bc\u08bd\u08be\u08bf\u08c0\u08c1\u08c2\u08c3\u08c4\u08c5\u08c6\u08c7\u08c8\u08c9\u08ca\u08cb\u08cc\u08cd\u08ce\u08cf\u08d0\u08d1\u08d2\u08d3\u08d4\u08d5\u08d6\u08d7\u08d8\u08d9\u08da\u08db\u08dc\u08dd\u08de\u08df\u08e0\u08e1\u08e2\u08e3\u08e4\u08e5\u08e6\u08e7\u08e8\u08e9\u08ea\u08eb\u08ec\u08ed\u08ee\u08ef\u08f0\u08f1\u08f2\u08f3\u08f4\u08f5\u08f6\u08f7\u08f8\u08f9\u08fa\u08fb\u08fc\u08fd\u08fe\u08ff\u0900\u093a\u093b\u094e\u094f\u0955\u0956\u0957\u0971\u0972\u0973\u
 0974\u0975\u0976\u0977\u0978\u0979\u097a\u097b\u097c\u097e\u097f\u0980\u0984\u098d\u098e\u0991\u0992\u09a9\u09b1\u09b3\u09b4\u09b5\u09ba\u09bb\u09c5\u09c6\u09c9\u09ca\u09cf\u09d0\u09d1\u09d2\u09d3\u09d4\u09d5\u09d6\u09d8\u09d9\u09da\u09db\u09de\u09e4\u09e5\u09fb\u09fc\u09fd\u09fe\u09ff\u0a00\u0a04\u0a0b\u0a0c\u0a0d\u0a0e\u0a11\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a\u0a3b\u0a3d\u0a43\u0a44\u0a45\u0a46\u0a49\u0a4a\u0a4e\u0a4f\u0a50\u0a51\u0a52\u0a53\u0a54\u0a55\u0a56\u0a57\u0a58\u0a5d\u0a5f\u0a60\u0a61\u0a62\u0a63\u0a64\u0a65\u0a75\u0a76\u0a77\u0a78\u0a79\u0a7a\u0a7b\u0a7c\u0a7d\u0a7e\u0a7f\u0a80\u0a84\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba\u0abb\u0ac6\u0aca\u0ace\u0acf\u0ad1\u0ad2\u0ad3\u0ad4\u0ad5\u0ad6\u0ad7\u0ad8\u0ad9\u0ada\u0adb\u0adc\u0add\u0ade\u0adf\u0ae4\u0ae5\u0af0\u0af2\u0af3\u0af4\u0af5\u0af6\u0af7\u0af8\u0af9\u0afa\u0afb\u0afc\u0afd\u0afe\u0aff\u0b00\u0b04\u0b0d\u0b0e\u0b11\u0b12\u0b29\u0b31\u0b34\u0b3a\u0b3b\u0b44\u0b45\u0b46\u0b49\u0b4a\u0b4e\u0b4f\u0b50\u0b51\u0b52\u0b53\u0
 b54\u0b55\u0b58\u0b59\u0b5a\u0b5b\u0b5e\u0b62\u0b63\u0b64\u0b65\u0b72\u0b73\u0b74\u0b75\u0b76\u0b77\u0b78\u0b79\u0b7a\u0b7b\u0b7c\u0b7d\u0b7e\u0b7f\u0b80\u0b81\u0b84\u0b8b\u0b8c\u0b8d\u0b91\u0b96\u0b97\u0b98\u0b9b\u0b9d\u0ba0\u0ba1\u0ba2\u0ba5\u0ba6\u0ba7\u0bab\u0bac\u0bad\u0bba\u0bbb\u0bbc\u0bbd\u0bc3\u0bc4\u0bc5\u0bc9\u0bce\u0bcf\u0bd0\u0bd1\u0bd2\u0bd3\u0bd4\u0bd5\u0bd6\u0bd8\u0bd9\u0bda\u0bdb\u0bdc\u0bdd\u0bde\u0bdf\u0be0\u0be1\u0be2\u0be3\u0be4\u0be5\u0bfb\u0bfc\u0bfd\u0bfe\u0bff\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a\u0c3b\u0c3c\u0c3d\u0c45\u0c49\u0c4e\u0c4f\u0c50\u0c51\u0c52\u0c53\u0c54\u0c57\u0c58\u0c59\u0c5a\u0c5b\u0c5c\u0c5d\u0c5e\u0c5f\u0c62\u0c63\u0c64\u0c65\u0c70\u0c71\u0c72\u0c73\u0c74\u0c75\u0c76\u0c77\u0c78\u0c79\u0c7a\u0c7b\u0c7c\u0c7d\u0c7e\u0c7f\u0c80\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba\u0cbb\u0cc5\u0cc9\u0cce\u0ccf\u0cd0\u0cd1\u0cd2\u0cd3\u0cd4\u0cd7\u0cd8\u0cd9\u0cda\u0cdb\u0cdc\u0cdd\u0cdf\u0ce2\u0ce3\u0ce4\u0ce5\u0cf0\u0cf1\u0cf2\u0cf3\u0cf4\u0cf5\u0c
 f6\u0cf7\u0cf8\u0cf9\u0cfa\u0cfb\u0cfc\u0cfd\u0cfe\u0cff\u0d00\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a\u0d3b\u0d3c\u0d3d\u0d44\u0d45\u0d49\u0d4e\u0d4f\u0d50\u0d51\u0d52\u0d53\u0d54\u0d55\u0d56\u0d58\u0d59\u0d5a\u0d5b\u0d5c\u0d5d\u0d5e\u0d5f\u0d62\u0d63\u0d64\u0d65\u0d70\u0d71\u0d72\u0d73\u0d74\u0d75\u0d76\u0d77\u0d78\u0d79\u0d7a\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f\u0d80\u0d81\u0d84\u0d97\u0d98\u0d99\u0db2\u0dbc\u0dbe\u0dbf\u0dc7\u0dc8\u0dc9\u0dcb\u0dcc\u0dcd\u0dce\u0dd5\u0dd7\u0de0\u0de1\u0de2\u0de3\u0de4\u0de5\u0de6\u0de7\u0de8\u0de9\u0dea\u0deb\u0dec\u0ded\u0dee\u0def\u0df0\u0df1\u0df5\u0df6\u0df7\u0df8\u0df9\u0dfa\u0dfb\u0dfc\u0dfd\u0dfe\u0dff\u0e00\u0e3b\u0e3c\u0e3d\u0e3e\u0e5c\u0e5d\u0e5e\u0e5f\u0e60\u0e61\u0e62\u0e63\u0e64\u0e65\u0e66\u0e67\u0e68\u0e69\u0e6a\u0e6b\u0e6c\u0e6d\u0e6e\u0e6f\u0e70\u0e71\u0e72\u0e73\u0e74\u0e75\u0e76\u0e77\u0e78\u0e79\u0e7a\u0e7b\u0e7c\u0e7d\u0e7e\u0e7f\u0e80\u0e83\u0e85\u0e86\u0e89\u0e8b\u0e8c\u0e8e\u0e8f\u0e90\u0e91\u0e92\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea
 8\u0ea9\u0eac\u0eba\u0ebe\u0ebf\u0ec5\u0ec7\u0ece\u0ecf\u0eda\u0edb\u0ede\u0edf\u0ee0\u0ee1\u0ee2\u0ee3\u0ee4\u0ee5\u0ee6\u0ee7\u0ee8\u0ee9\u0eea\u0eeb\u0eec\u0eed\u0eee\u0eef\u0ef0\u0ef1\u0ef2\u0ef3\u0ef4\u0ef5\u0ef6\u0ef7\u0ef8\u0ef9\u0efa\u0efb\u0efc\u0efd\u0efe\u0eff\u0f48\u0f6b\u0f6c\u0f6d\u0f6e\u0f6f\u0f70\u0f8c\u0f8d\u0f8e\u0f8f\u0f98\u0fbd\u0fcd\u0fce\u0fd2\u0fd3\u0fd4\u0fd5\u0fd6\u0fd7\u0fd8\u0fd9\u0fda\u0fdb\u0fdc\u0fdd\u0fde\u0fdf\u0fe0\u0fe1\u0fe2\u0fe3\u0fe4\u0fe5\u0fe6\u0fe7\u0fe8\u0fe9\u0fea\u0feb\u0fec\u0fed\u0fee\u0fef\u0ff0\u0ff1\u0ff2\u0ff3\u0ff4\u0ff5\u0ff6\u0ff7\u0ff8\u0ff9\u0ffa\u0ffb\u0ffc\u0ffd\u0ffe\u0fff\u1022\u1028\u102b\u1033\u1034\u1035\u103a\u103b\u103c\u103d\u103e\u103f\u105a\u105b\u105c\u105d\u105e\u105f\u1060\u1061\u1062\u1063\u1064\u1065\u1066\u1067\u1068\u1069\u106a\u106b\u106c\u106d\u106e\u106f\u1070\u1071\u1072\u1073\u1074\u1075\u1076\u1077\u1078\u1079\u107a\u107b\u107c\u107d\u107e\u107f\u1080\u1081\u1082\u1083\u1084\u1085\u1086\u1087\u1088\u1089
 \u108a\u108b\u108c\u108d\u108e\u108f\u1090\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\u109a\u109b\u109c\u109d\u109e\u109f\u10c6\u10c7\u10c8\u10c9\u10ca\u10cb\u10cc\u10cd\u10ce\u10cf\u10fd\u10fe\u10ff\u115a\u115b\u115c\u115d\u115e\u11a3\u11a4\u11a5\u11a6\u11a7\u11fa\u11fb\u11fc\u11fd\u11fe\u11ff\u1249\u124e\u124f\u1257\u1259\u125e\u125f\u1289\u128e\u128f\u12b1\u12b6\u12b7\u12bf\u12c1\u12c6\u12c7\u12d7\u1311\u1316\u1317\u135b\u135c\u135d\u135e\u137d\u137e\u137f\u139a\u139b\u139c\u139d\u139e\u139f\u13f5\u13f6\u13f7\u13f8\u13f9\u13fa\u13fb\u13fc\u13fd\u13fe\u13ff\u1400\u1677\u1678\u1679\u167a\u167b\u167c\u167d\u167e\u167f\u169d\u169e\u169f\u16f1\u16f2\u16f3\u16f4\u16f5\u16f6\u16f7\u16f8\u16f9\u16fa\u16fb\u16fc\u16fd\u16fe\u16ff\u170d\u1715\u1716\u1717\u1718\u1719\u171a\u171b\u171c\u171d\u171e\u171f\u1737\u1738\u1739\u173a\u173b\u173c\u173d\u173e\u173f\u1754\u1755\u1756\u1757\u1758\u1759\u175a\u175b\u175c\u175d\u175e\u175f\u176d\u1771\u1774\u1775\u1776\u1777\u1778\u1779\u177a\
 u177b\u177c\u177d\u177e\u177f\u17de\u17df\u17ea\u17eb\u17ec\u17ed\u17ee\u17ef\u17fa\u17fb\u17fc\u17fd\u17fe\u17ff\u180f\u181a\u181b\u181c\u181d\u181e\u181f\u1878\u1879\u187a\u187b\u187c\u187d\u187e\u187f\u18aa\u18ab\u18ac\u18ad\u18ae\u18af\u18b0\u18b1\u18b2\u18b3\u18b4\u18b5\u18b6\u18b7\u18b8\u18b9\u18ba\u18bb\u18bc\u18bd\u18be\u18bf\u18c0\u18c1\u18c2\u18c3\u18c4\u18c5\u18c6\u18c7\u18c8\u18c9\u18ca\u18cb\u18cc\u18cd\u18ce\u18cf\u18d0\u18d1\u18d2\u18d3\u18d4\u18d5\u18d6\u18d7\u18d8\u18d9\u18da\u18db\u18dc\u18dd\u18de\u18df\u18e0\u18e1\u18e2\u18e3\u18e4\u18e5\u18e6\u18e7\u18e8\u18e9\u18ea\u18eb\u18ec\u18ed\u18ee\u18ef\u18f0\u18f1\u18f2\u18f3\u18f4\u18f5\u18f6\u18f7\u18f8\u18f9\u18fa\u18fb\u18fc\u18fd\u18fe\u18ff\u191d\u191e\u191f\u192c\u192d\u192e\u192f\u193c\u193d\u193e\u193f\u1941\u1942\u1943\u196e\u196f\u1975\u1976\u1977\u1978\u1979\u197a\u197b\u197c\u197d\u197e\u197f\u19aa\u19ab\u19ac\u19ad\u19ae\u19af\u19ca\u19cb\u19cc\u19cd\u19ce\u19cf\u19da\u19db\u19dc\u19dd\u1a1c\u1a1d\u1a20\u
 1a21\u1a22\u1a23\u1a24\u1a25\u1a26\u1a27\u1a28\u1a29\u1a2a\u1a2b\u1a2c\u1a2d\u1a2e\u1a2f\u1a30\u1a31\u1a32\u1a33\u1a34\u1a35\u1a36\u1a37\u1a38\u1a39\u1a3a\u1a3b\u1a3c\u1a3d\u1a3e\u1a3f\u1a40\u1a41\u1a42\u1a43\u1a44\u1a45\u1a46\u1a47\u1a48\u1a49\u1a4a\u1a4b\u1a4c\u1a4d\u1a4e\u1a4f\u1a50\u1a51\u1a52\u1a53\u1a54\u1a55\u1a56\u1a57\u1a58\u1a59\u1a5a\u1a5b\u1a5c\u1a5d\u1a5e\u1a5f\u1a60\u1a61\u1a62\u1a63\u1a64\u1a65\u1a66\u1a67\u1a68\u1a69\u1a6a\u1a6b\u1a6c\u1a6d\u1a6e\u1a6f\u1a70\u1a71\u1a72\u1a73\u1a74\u1a75\u1a76\u1a77\u1a78\u1a79\u1a7a\u1a7b\u1a7c\u1a7d\u1a7e\u1a7f\u1a80\u1a81\u1a82\u1a83\u1a84\u1a85\u1a86\u1a87\u1a88\u1a89\u1a8a\u1a8b\u1a8c\u1a8d\u1a8e\u1a8f\u1a90\u1a91\u1a92\u1a93\u1a94\u1a95\u1a96\u1a97\u1a98\u1a99\u1a9a\u1a9b\u1a9c\u1a9d\u1a9e\u1a9f\u1aa0\u1aa1\u1aa2\u1aa3\u1aa4\u1aa5\u1aa6\u1aa7\u1aa8\u1aa9\u1aaa\u1aab\u1aac\u1aad\u1aae\u1aaf\u1ab0\u1ab1\u1ab2\u1ab3\u1ab4\u1ab5\u1ab6\u1ab7\u1ab8\u1ab9\u1aba\u1abb\u1abc\u1abd\u1abe\u1abf\u1ac0\u1ac1\u1ac2\u1ac3\u1ac4\u1ac5\u1ac6\u1
 ac7\u1ac8\u1ac9\u1aca\u1acb\u1acc\u1acd\u1ace\u1acf\u1ad0\u1ad1\u1ad2\u1ad3\u1ad4\u1ad5\u1ad6\u1ad7\u1ad8\u1ad9\u1ada\u1adb\u1adc\u1add\u1ade\u1adf\u1ae0\u1ae1\u1ae2\u1ae3\u1ae4\u1ae5\u1ae6\u1ae7\u1ae8\u1ae9\u1aea\u1aeb\u1aec\u1aed\u1aee\u1aef\u1af0\u1af1\u1af2\u1af3\u1af4\u1af5\u1af6\u1af7\u1af8\u1af9\u1afa\u1afb\u1afc\u1afd\u1afe\u1aff\u1b00\u1b01\u1b02\u1b03\u1b04\u1b05\u1b06\u1b07\u1b08\u1b09\u1b0a\u1b0b\u1b0c\u1b0d\u1b0e\u1b0f\u1b10\u1b11\u1b12\u1b13\u1b14\u1b15\u1b16\u1b17\u1b18\u1b19\u1b1a\u1b1b\u1b1c\u1b1d\u1b1e\u1b1f\u1b20\u1b21\u1b22\u1b23\u1b24\u1b25\u1b26\u1b27\u1b28\u1b29\u1b2a\u1b2b\u1b2c\u1b2d\u1b2e\u1b2f\u1b30\u1b31\u1b32\u1b33\u1b34\u1b35\u1b36\u1b37\u1b38\u1b39\u1b3a\u1b3b\u1b3c\u1b3d\u1b3e\u1b3f\u1b40\u1b41\u1b42\u1b43\u1b44\u1b45\u1b46\u1b47\u1b48\u1b49\u1b4a\u1b4b\u1b4c\u1b4d\u1b4e\u1b4f\u1b50\u1b51\u1b52\u1b53\u1b54\u1b55\u1b56\u1b57\u1b58\u1b59\u1b5a\u1b5b\u1b5c\u1b5d\u1b5e\u1b5f\u1b60\u1b61\u1b62\u1b63\u1b64\u1b65\u1b66\u1b67\u1b68\u1b69\u1b6a\u1b6b\u1b6c\u1b
 6d\u1b6e\u1b6f\u1b70\u1b71\u1b72\u1b73\u1b74\u1b75\u1b76\u1b77\u1b78\u1b79\u1b7a\u1b7b\u1b7c\u1b7d\u1b7e\u1b7f\u1b80\u1b81\u1b82\u1b83\u1b84\u1b85\u1b86\u1b87\u1b88\u1b89\u1b8a\u1b8b\u1b8c\u1b8d\u1b8e\u1b8f\u1b90\u1b91\u1b92\u1b93\u1b94\u1b95\u1b96\u1b97\u1b98\u1b99\u1b9a\u1b9b\u1b9c\u1b9d\u1b9e\u1b9f\u1ba0\u1ba1\u1ba2\u1ba3\u1ba4\u1ba5\u1ba6\u1ba7\u1ba8\u1ba9\u1baa\u1bab\u1bac\u1bad\u1bae\u1baf\u1bb0\u1bb1\u1bb2\u1bb3\u1bb4\u1bb5\u1bb6\u1bb7\u1bb8\u1bb9\u1bba\u1bbb\u1bbc\u1bbd\u1bbe\u1bbf\u1bc0\u1bc1\u1bc2\u1bc3\u1bc4\u1bc5\u1bc6\u1bc7\u1bc8\u1bc9\u1bca\u1bcb\u1bcc\u1bcd\u1bce\u1bcf\u1bd0\u1bd1\u1bd2\u1bd3\u1bd4\u1bd5\u1bd6\u1bd7\u1bd8\u1bd9\u1bda\u1bdb\u1bdc\u1bdd\u1bde\u1bdf\u1be0\u1be1\u1be2\u1be3\u1be4\u1be5\u1be6\u1be7\u1be8\u1be9\u1bea\u1beb\u1bec\u1bed\u1bee\u1bef\u1bf0\u1bf1\u1bf2\u1bf3\u1bf4\u1bf5\u1bf6\u1bf7\u1bf8\u1bf9\u1bfa\u1bfb\u1bfc\u1bfd\u1bfe\u1bff\u1c00\u1c01\u1c02\u1c03\u1c04\u1c05\u1c06\u1c07\u1c08\u1c09\u1c0a\u1c0b\u1c0c\u1c0d\u1c0e\u1c0f\u1c10\u1c11\u1c12\u1c1
 3\u1c14\u1c15\u1c16\u1c17\u1c18\u1c19\u1c1a\u1c1b\u1c1c\u1c1d\u1c1e\u1c1f\u1c20\u1c21\u1c22\u1c23\u1c24\u1c25\u1c26\u1c27\u1c28\u1c29\u1c2a\u1c2b\u1c2c\u1c2d\u1c2e\u1c2f\u1c30\u1c31\u1c32\u1c33\u1c34\u1c35\u1c36\u1c37\u1c38\u1c39\u1c3a\u1c3b\u1c3c\u1c3d\u1c3e\u1c3f\u1c40\u1c41\u1c42\u1c43\u1c44\u1c45\u1c46\u1c47\u1c48\u1c49\u1c4a\u1c4b\u1c4c\u1c4d\u1c4e\u1c4f\u1c50\u1c51\u1c52\u1c53\u1c54\u1c55\u1c56\u1c57\u1c58\u1c59\u1c5a\u1c5b\u1c5c\u1c5d\u1c5e\u1c5f\u1c60\u1c61\u1c62\u1c63\u1c64\u1c65\u1c66\u1c67\u1c68\u1c69\u1c6a\u1c6b\u1c6c\u1c6d\u1c6e\u1c6f\u1c70\u1c71\u1c72\u1c73\u1c74\u1c75\u1c76\u1c77\u1c78\u1c79\u1c7a\u1c7b\u1c7c\u1c7d\u1c7e\u1c7f\u1c80\u1c81\u1c82\u1c83\u1c84\u1c85\u1c86\u1c87\u1c88\u1c89\u1c8a\u1c8b\u1c8c\u1c8d\u1c8e\u1c8f\u1c90\u1c91\u1c92\u1c93\u1c94\u1c95\u1c96\u1c97\u1c98\u1c99\u1c9a\u1c9b\u1c9c\u1c9d\u1c9e\u1c9f\u1ca0\u1ca1\u1ca2\u1ca3\u1ca4\u1ca5\u1ca6\u1ca7\u1ca8\u1ca9\u1caa\u1cab\u1cac\u1cad\u1cae\u1caf\u1cb0\u1cb1\u1cb2\u1cb3\u1cb4\u1cb5\u1cb6\u1cb7\u1cb8\u1cb9
 \u1cba\u1cbb\u1cbc\u1cbd\u1cbe\u1cbf\u1cc0\u1cc1\u1cc2\u1cc3\u1cc4\u1cc5\u1cc6\u1cc7\u1cc8\u1cc9\u1cca\u1ccb\u1ccc\u1ccd\u1cce\u1ccf\u1cd0\u1cd1\u1cd2\u1cd3\u1cd4\u1cd5\u1cd6\u1cd7\u1cd8\u1cd9\u1cda\u1cdb\u1cdc\u1cdd\u1cde\u1cdf\u1ce0\u1ce1\u1ce2\u1ce3\u1ce4\u1ce5\u1ce6\u1ce7\u1ce8\u1ce9\u1cea\u1ceb\u1cec\u1ced\u1cee\u1cef\u1cf0\u1cf1\u1cf2\u1cf3\u1cf4\u1cf5\u1cf6\u1cf7\u1cf8\u1cf9\u1cfa\u1cfb\u1cfc\u1cfd\u1cfe\u1cff\u1dc4\u1dc5\u1dc6\u1dc7\u1dc8\u1dc9\u1dca\u1dcb\u1dcc\u1dcd\u1dce\u1dcf\u1dd0\u1dd1\u1dd2\u1dd3\u1dd4\u1dd5\u1dd6\u1dd7\u1dd8\u1dd9\u1dda\u1ddb\u1ddc\u1ddd\u1dde\u1ddf\u1de0\u1de1\u1de2\u1de3\u1de4\u1de5\u1de6\u1de7\u1de8\u1de9\u1dea\u1deb\u1dec\u1ded\u1dee\u1def\u1df0\u1df1\u1df2\u1df3\u1df4\u1df5\u1df6\u1df7\u1df8\u1df9\u1dfa\u1dfb\u1dfc\u1dfd\u1dfe\u1dff\u1e9c\u1e9d\u1e9e\u1e9f\u1efa\u1efb\u1efc\u1efd\u1efe\u1eff\u1f16\u1f17\u1f1e\u1f1f\u1f46\u1f47\u1f4e\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e\u1f7f\u1fb5\u1fc5\u1fd4\u1fd5\u1fdc\u1ff0\u1ff1\u1ff5\u1fff\u2064\u2065\u2066\
 u2067\u2068\u2069\u2072\u2073\u208f\u2095\u2096\u2097\u2098\u2099\u209a\u209b\u209c\u209d\u209e\u209f\u20b6\u20b7\u20b8\u20b9\u20ba\u20bb\u20bc\u20bd\u20be\u20bf\u20c0\u20c1\u20c2\u20c3\u20c4\u20c5\u20c6\u20c7\u20c8\u20c9\u20ca\u20cb\u20cc\u20cd\u20ce\u20cf\u20ec\u20ed\u20ee\u20ef\u20f0\u20f1\u20f2\u20f3\u20f4\u20f5\u20f6\u20f7\u20f8\u20f9\u20fa\u20fb\u20fc\u20fd\u20fe\u20ff\u214d\u214e\u214f\u2150\u2151\u2152\u2184\u2185\u2186\u2187\u2188\u2189\u218a\u218b\u218c\u218d\u218e\u218f\u23dc\u23dd\u23de\u23df\u23e0\u23e1\u23e2\u23e3\u23e4\u23e5\u23e6\u23e7\u23e8\u23e9\u23ea\u23eb\u23ec\u23ed\u23ee\u23ef\u23f0\u23f1\u23f2\u23f3\u23f4\u23f5\u23f6\u23f7\u23f8\u23f9\u23fa\u23fb\u23fc\u23fd\u23fe\u23ff\u2427\u2428\u2429\u242a\u242b\u242c\u242d\u242e\u242f\u2430\u2431\u2432\u2433\u2434\u2435\u2436\u2437\u2438\u2439\u243a\u243b\u243c\u243d\u243e\u243f\u244b\u244c\u244d\u244e\u244f\u2450\u2451\u2452\u2453\u2454\u2455\u2456\u2457\u2458\u2459\u245a\u245b\u245c\u245d\u245e\u245f\u269d\u269e\u269f\u
 26b2\u26b3\u26b4\u26b5\u26b6\u26b7\u26b8\u26b9\u26ba\u26bb\u26bc\u26bd\u26be\u26bf\u26c0\u26c1\u26c2\u26c3\u26c4\u26c5\u26c6\u26c7\u26c8\u26c9\u26ca\u26cb\u26cc\u26cd\u26ce\u26cf\u26d0\u26d1\u26d2\u26d3\u26d4\u26d5\u26d6\u26d7\u26d8\u26d9\u26da\u26db\u26dc\u26dd\u26de\u26df\u26e0\u26e1\u26e2\u26e3\u26e4\u26e5\u26e6\u26e7\u26e8\u26e9\u26ea\u26eb\u26ec\u26ed\u26ee\u26ef\u26f0\u26f1\u26f2\u26f3\u26f4\u26f5\u26f6\u26f7\u26f8\u26f9\u26fa\u26fb\u26fc\u26fd\u26fe\u26ff\u2700\u2705\u270a\u270b\u2728\u274c\u274e\u2753\u2754\u2755\u2757\u275f\u2760\u2795\u2796\u2797\u27b0\u27bf\u27c7\u27c8\u27c9\u27ca\u27cb\u27cc\u27cd\u27ce\u27cf\u27ec\u27ed\u27ee\u27ef\u2b14\u2b15\u2b16\u2b17\u2b18\u2b19\u2b1a\u2b1b\u2b1c\u2b1d\u2b1e\u2b1f\u2b20\u2b21\u2b22\u2b23\u2b24\u2b25\u2b26\u2b27\u2b28\u2b29\u2b2a\u2b2b\u2b2c\u2b2d\u2b2e\u2b2f\u2b30\u2b31\u2b32\u2b33\u2b34\u2b35\u2b36\u2b37\u2b38\u2b39\u2b3a\u2b3b\u2b3c\u2b3d\u2b3e\u2b3f\u2b40\u2b41\u2b42\u2b43\u2b44\u2b45\u2b46\u2b47\u2b48\u2b49\u2b4a\u2b4b\u2b4c\u2
 b4d\u2b4e\u2b4f\u2b50\u2b51\u2b52\u2b53\u2b54\u2b55\u2b56\u2b57\u2b58\u2b59\u2b5a\u2b5b\u2b5c\u2b5d\u2b5e\u2b5f\u2b60\u2b61\u2b62\u2b63\u2b64\u2b65\u2b66\u2b67\u2b68\u2b69\u2b6a\u2b6b\u2b6c\u2b6d\u2b6e\u2b6f\u2b70\u2b71\u2b72\u2b73\u2b74\u2b75\u2b76\u2b77\u2b78\u2b79\u2b7a\u2b7b\u2b7c\u2b7d\u2b7e\u2b7f\u2b80\u2b81\u2b82\u2b83\u2b84\u2b85\u2b86\u2b87\u2b88\u2b89\u2b8a\u2b8b\u2b8c\u2b8d\u2b8e\u2b8f\u2b90\u2b91\u2b92\u2b93\u2b94\u2b95\u2b96\u2b97\u2b98\u2b99\u2b9a\u2b9b\u2b9c\u2b9d\u2b9e\u2b9f\u2ba0\u2ba1\u2ba2\u2ba3\u2ba4\u2ba5\u2ba6\u2ba7\u2ba8\u2ba9\u2baa\u2bab\u2bac\u2bad\u2bae\u2baf\u2bb0\u2bb1\u2bb2\u2bb3\u2bb4\u2bb5\u2bb6\u2bb7\u2bb8\u2bb9\u2bba\u2bbb\u2bbc\u2bbd\u2bbe\u2bbf\u2bc0\u2bc1\u2bc2\u2bc3\u2bc4\u2bc5\u2bc6\u2bc7\u2bc8\u2bc9\u2bca\u2bcb\u2bcc\u2bcd\u2bce\u2bcf\u2bd0\u2bd1\u2bd2\u2bd3\u2bd4\u2bd5\u2bd6\u2bd7\u2bd8\u2bd9\u2bda\u2bdb\u2bdc\u2bdd\u2bde\u2bdf\u2be0\u2be1\u2be2\u2be3\u2be4\u2be5\u2be6\u2be7\u2be8\u2be9\u2bea\u2beb\u2bec\u2bed\u2bee\u2bef\u2bf0\u2bf1\u2bf2\u2b
 f3\u2bf4\u2bf5\u2bf6\u2bf7\u2bf8\u2bf9\u2bfa\u2bfb\u2bfc\u2bfd\u2bfe\u2bff\u2c2f\u2c5f\u2c60\u2c61\u2c62\u2c63\u2c64\u2c65\u2c66\u2c67\u2c68\u2c69\u2c6a\u2c6b\u2c6c\u2c6d\u2c6e\u2c6f\u2c70\u2c71\u2c72\u2c73\u2c74\u2c75\u2c76\u2c77\u2c78\u2c79\u2c7a\u2c7b\u2c7c\u2c7d\u2c7e\u2c7f\u2ceb\u2cec\u2ced\u2cee\u2cef\u2cf0\u2cf1\u2cf2\u2cf3\u2cf4\u2cf5\u2cf6\u2cf7\u2cf8\u2d26\u2d27\u2d28\u2d29\u2d2a\u2d2b\u2d2c\u2d2d\u2d2e\u2d2f\u2d66\u2d67\u2d68\u2d69\u2d6a\u2d6b\u2d6c\u2d6d\u2d6e\u2d70\u2d71\u2d72\u2d73\u2d74\u2d75\u2d76\u2d77\u2d78\u2d79\u2d7a\u2d7b\u2d7c\u2d7d\u2d7e\u2d7f\u2d97\u2d98\u2d99\u2d9a\u2d9b\u2d9c\u2d9d\u2d9e\u2d9f\u2da7\u2daf\u2db7\u2dbf\u2dc7\u2dcf\u2dd7\u2ddf\u2de0\u2de1\u2de2\u2de3\u2de4\u2de5\u2de6\u2de7\u2de8\u2de9\u2dea\u2deb\u2dec\u2ded\u2dee\u2def\u2df0\u2df1\u2df2\u2df3\u2df4\u2df5\u2df6\u2df7\u2df8\u2df9\u2dfa\u2dfb\u2dfc\u2dfd\u2dfe\u2dff\u2e18\u2e19\u2e1a\u2e1b\u2e1e\u2e1f\u2e20\u2e21\u2e22\u2e23\u2e24\u2e25\u2e26\u2e27\u2e28\u2e29\u2e2a\u2e2b\u2e2c\u2e2d\u2e2e\u2e2
 f\u2e30\u2e31\u2e32\u2e33\u2e34\u2e35\u2e36\u2e37\u2e38\u2e39\u2e3a\u2e3b\u2e3c\u2e3d\u2e3e\u2e3f\u2e40\u2e41\u2e42\u2e43\u2e44\u2e45\u2e46\u2e47\u2e48\u2e49\u2e4a\u2e4b\u2e4c\u2e4d\u2e4e\u2e4f\u2e50\u2e51\u2e52\u2e53\u2e54\u2e55\u2e56\u2e57\u2e58\u2e59\u2e5a\u2e5b\u2e5c\u2e5d\u2e5e\u2e5f\u2e60\u2e61\u2e62\u2e63\u2e64\u2e65\u2e66\u2e67\u2e68\u2e69\u2e6a\u2e6b\u2e6c\u2e6d\u2e6e\u2e6f\u2e70\u2e71\u2e72\u2e73\u2e74\u2e75\u2e76\u2e77\u2e78\u2e79\u2e7a\u2e7b\u2e7c\u2e7d\u2e7e\u2e7f\u2e9a\u2ef4\u2ef5\u2ef6\u2ef7\u2ef8\u2ef9\u2efa\u2efb\u2efc\u2efd\u2efe\u2eff\u2fd6\u2fd7\u2fd8\u2fd9\u2fda\u2fdb\u2fdc\u2fdd\u2fde\u2fdf\u2fe0\u2fe1\u2fe2\u2fe3\u2fe4\u2fe5\u2fe6\u2fe7\u2fe8\u2fe9\u2fea\u2feb\u2fec\u2fed\u2fee\u2fef\u2ffc\u2ffd\u2ffe\u2fff\u3040\u3097\u3098\u3100\u3101\u3102\u3103\u3104\u312d\u312e\u312f\u3130\u318f\u31b8\u31b9\u31ba\u31bb\u31bc\u31bd\u31be\u31bf\u31d0\u31d1\u31d2\u31d3\u31d4\u31d5\u31d6\u31d7\u31d8\u31d9\u31da\u31db\u31dc\u31dd\u31de\u31df\u31e0\u31e1\u31e2\u31e3\u31e4\u31e5
 \u31e6\u31e7\u31e8\u31e9\u31ea\u31eb\u31ec\u31ed\u31ee\u31ef\u321f\u3244\u3245\u3246\u3247\u3248\u3249\u324a\u324b\u324c\u324d\u324e\u324f\u32ff\u4db6\u4db7\u4db8\u4db9\u4dba\u4dbb\u4dbc\u4dbd\u4dbe\u4dbf\u9fbc\u9fbd\u9fbe\u9fbf\u9fc0\u9fc1\u9fc2\u9fc3\u9fc4\u9fc5\u9fc6\u9fc7\u9fc8\u9fc9\u9fca\u9fcb\u9fcc\u9fcd\u9fce\u9fcf\u9fd0\u9fd1\u9fd2\u9fd3\u9fd4\u9fd5\u9fd6\u9fd7\u9fd8\u9fd9\u9fda\u9fdb\u9fdc\u9fdd\u9fde\u9fdf\u9fe0\u9fe1\u9fe2\u9fe3\u9fe4\u9fe5\u9fe6\u9fe7\u9fe8\u9fe9\u9fea\u9feb\u9fec\u9fed\u9fee\u9fef\u9ff0\u9ff1\u9ff2\u9ff3\u9ff4\u9ff5\u9ff6\u9ff7\u9ff8\u9ff9\u9ffa\u9ffb\u9ffc\u9ffd\u9ffe\u9fff\ua48d\ua48e\ua48f\ua4c7\ua4c8\ua4c9\ua4ca\ua4cb\ua4cc\ua4cd\ua4ce\ua4cf\ua4d0\ua4d1\ua4d2\ua4d3\ua4d4\ua4d5\ua4d6\ua4d7\ua4d8\ua4d9\ua4da\ua4db\ua4dc\ua4dd\ua4de\ua4df\ua4e0\ua4e1\ua4e2\ua4e3\ua4e4\ua4e5\ua4e6\ua4e7\ua4e8\ua4e9\ua4ea\ua4eb\ua4ec\ua4ed\ua4ee\ua4ef\ua4f0\ua4f1\ua4f2\ua4f3\ua4f4\ua4f5\ua4f6\ua4f7\ua4f8\ua4f9\ua4fa\ua4fb\ua4fc\ua4fd\ua4fe\ua4ff\ua500\ua501\ua502\ua503\
 ua504\ua505\ua506\ua507\ua508\ua509\ua50a\ua50b\ua50c\ua50d\ua50e\ua50f\ua510\ua511\ua512\ua513\ua514\ua515\ua516\ua517\ua518\ua519\ua51a\ua51b\ua51c\ua51d\ua51e\ua51f\ua520\ua521\ua522\ua523\ua524\ua525\ua526\ua527\ua528\ua529\ua52a\ua52b\ua52c\ua52d\ua52e\ua52f\ua530\ua531\ua532\ua533\ua534\ua535\ua536\ua537\ua538\ua539\ua53a\ua53b\ua53c\ua53d\ua53e\ua53f\ua540\ua541\ua542\ua543\ua544\ua545\ua546\ua547\ua548\ua549\ua54a\ua54b\ua54c\ua54d\ua54e\ua54f\ua550\ua551\ua552\ua553\ua554\ua555\ua556\ua557\ua558\ua559\ua55a\ua55b\ua55c\ua55d\ua55e\ua55f\ua560\ua561\ua562\ua563\ua564\ua565\ua566\ua567\ua568\ua569\ua56a\ua56b\ua56c\ua56d\ua56e\ua56f\ua570\ua571\ua572\ua573\ua574\ua575\ua576\ua577\ua578\ua579\ua57a\ua57b\ua57c\ua57d\ua57e\ua57f\ua580\ua581\ua582\ua583\ua584\ua585\ua586\ua587\ua588\ua589\ua58a\ua58b\ua58c\ua58d\ua58e\ua58f\ua590\ua591\ua592\ua593\ua594\ua595\ua596\ua597\ua598\ua599\ua59a\ua59b\ua59c\ua59d\ua59e\ua59f\ua5a0\ua5a1\ua5a2\ua5a3\ua5a4\ua5a5\ua5a6\ua5a7\ua5a8\ua5a9\u
 a5aa\ua5ab\ua5ac\ua5ad\ua5ae\ua5af\ua5b0\ua5b1\ua5b2\ua5b3\ua5b4\ua5b5\ua5b6\ua5b7\ua5b8\ua5b9\ua5ba\ua5bb\ua5bc\ua5bd\ua5be\ua5bf\ua5c0\ua5c1\ua5c2\ua5c3\ua5c4\ua5c5\ua5c6\ua5c7\ua5c8\ua5c9\ua5ca\ua5cb\ua5cc\ua5cd\ua5ce\ua5cf\ua5d0\ua5d1\ua5d2\ua5d3\ua5d4\ua5d5\ua5d6\ua5d7\ua5d8\ua5d9\ua5da\ua5db\ua5dc\ua5dd\ua5de\ua5df\ua5e0\ua5e1\ua5e2\ua5e3\ua5e4\ua5e5\ua5e6\ua5e7\ua5e8\ua5e9\ua5ea\ua5eb\ua5ec\ua5ed\ua5ee\ua5ef\ua5f0\ua5f1\ua5f2\ua5f3\ua5f4\ua5f5\ua5f6\ua5f7\ua5f8\ua5f9\ua5fa\ua5fb\ua5fc\ua5fd\ua5fe\ua5ff\ua600\ua601\ua602\ua603\ua604\ua605\ua606\ua607\ua608\ua609\ua60a\ua60b\ua60c\ua60d\ua60e\ua60f\ua610\ua611\ua612\ua613\ua614\ua615\ua616\ua617\ua618\ua619\ua61a\ua61b\ua61c\ua61d\ua61e\ua61f\ua620\ua621\ua622\ua623\ua624\ua625\ua626\ua627\ua628\ua629\ua62a\ua62b\ua62c\ua62d\ua62e\ua62f\ua630\ua631\ua632\ua633\ua634\ua635\ua636\ua637\ua638\ua639\ua63a\ua63b\ua63c\ua63d\ua63e\ua63f\ua640\ua641\ua642\ua643\ua644\ua645\ua646\ua647\ua648\ua649\ua64a\ua64b\ua64c\ua64d\ua64e\ua64f\ua
 650\ua651\ua652\ua653\ua654\ua655\ua656\ua657\ua658\ua659\ua65a\ua65b\ua65c\ua65d\ua65e\ua65f\ua660\ua661\ua662\ua663\ua664\ua665\ua666\ua667\ua668\ua669\ua66a\ua66b\ua66c\ua66d\ua66e\ua66f\ua670\ua671\ua672\ua673\ua674\ua675\ua676\ua677\ua678\ua679\ua67a\ua67b\ua67c\ua67d\ua67e\ua67f\ua680\ua681\ua682\ua683\ua684\ua685\ua686\ua687\ua688\ua689\ua68a\ua68b\ua68c\ua68d\ua68e\ua68f\ua690\ua691\ua692\ua693\ua694\ua695\ua696\ua697\ua698\ua699\ua69a\ua69b\ua69c\ua69d\ua69e\ua69f\ua6a0\ua6a1\ua6a2\ua6a3\ua6a4\ua6a5\ua6a6\ua6a7\ua6a8\ua6a9\ua6aa\ua6ab\ua6ac\ua6ad\ua6ae\ua6af\ua6b0\ua6b1\ua6b2\ua6b3\ua6b4\ua6b5\ua6b6\ua6b7\ua6b8\ua6b9\ua6ba\ua6bb\ua6bc\ua6bd\ua6be\ua6bf\ua6c0\ua6c1\ua6c2\ua6c3\ua6c4\ua6c5\ua6c6\ua6c7\ua6c8\ua6c9\ua6ca\ua6cb\ua6cc\ua6cd\ua6ce\ua6cf\ua6d0\ua6d1\ua6d2\ua6d3\ua6d4\ua6d5\ua6d6\ua6d7\ua6d8\ua6d9\ua6da\ua6db\ua6dc\ua6dd\ua6de\ua6df\ua6e0\ua6e1\ua6e2\ua6e3\ua6e4\ua6e5\ua6e6\ua6e7\ua6e8\ua6e9\ua6ea\ua6eb\ua6ec\ua6ed\ua6ee\ua6ef\ua6f0\ua6f1\ua6f2\ua6f3\ua6f4\ua6f5\ua6
 f6\ua6f7\ua6f8\ua6f9\ua6fa\ua6fb\ua6fc\ua6fd\ua6fe\ua6ff\ua717\ua718\ua719\ua71a\ua71b\ua71c\ua71d\ua71e\ua71f\ua720\ua721\ua722\ua723\ua724\ua725\ua726\ua727\ua728\ua729\ua72a\ua72b\ua72c\ua72d\ua72e\ua72f\ua730\ua731\ua732\ua733\ua734\ua735\ua736\ua737\ua738\ua739\ua73a\ua73b\ua73c\ua73d\ua73e\ua73f\ua740\ua741\ua742\ua743\ua744\ua745\ua746\ua747\ua748\ua749\ua74a\ua74b\ua74c\ua74d\ua74e\ua74f\ua750\ua751\ua752\ua753\ua754\ua755\ua756\ua757\ua758\ua759\ua75a\ua75b\ua75c\ua75d\ua75e\ua75f\ua760\ua761\ua762\ua763\ua764\ua765\ua766\ua767\ua768\ua769\ua76a\ua76b\ua76c\ua76d\ua76e\ua76f\ua770\ua771\ua772\ua773\ua774\ua775\ua776\ua777\ua778\ua779\ua77a\ua77b\ua77c\ua77d\ua77e\ua77f\ua780\ua781\ua782\ua783\ua784\ua785\ua786\ua787\ua788\ua789\ua78a\ua78b\ua78c\ua78d\ua78e\ua78f\ua790\ua791\ua792\ua793\ua794\ua795\ua796\ua797\ua798\ua799\ua79a\ua79b\ua79c\ua79d\ua79e\ua79f\ua7a0\ua7a1\ua7a2\ua7a3\ua7a4\ua7a5\ua7a6\ua7a7\ua7a8\ua7a9\ua7aa\ua7ab\ua7ac\ua7ad\ua7ae\ua7af\ua7b0\ua7b1\ua7b2\ua7b
 3\ua7b4\ua7b5\ua7b6\ua7b7\ua7b8\ua7b9\ua7ba\ua7bb\ua7bc\ua7bd\ua7be\ua7bf\ua7c0\ua7c1\ua7c2\ua7c3\ua7c4\ua7c5\ua7c6\ua7c7\ua7c8\ua7c9\ua7ca\ua7cb\ua7cc\ua7cd\ua7ce\ua7cf\ua7d0\ua7d1\ua7d2\ua7d3\ua7d4\ua7d5\ua7d6\ua7d7\ua7d8\ua7d9\ua7da\ua7db\ua7dc\ua7dd\ua7de\ua7df\ua7e0\ua7e1\ua7e2\ua7e3\ua7e4\ua7e5\ua7e6\ua7e7\ua7e8\ua7e9\ua7ea\ua7eb\ua7ec\ua7ed\ua7ee\ua7ef\ua7f0\ua7f1\ua7f2\ua7f3\ua7f4\ua7f5\ua7f6\ua7f7\ua7f8\ua7f9\ua7fa\ua7fb\ua7fc\ua7fd\ua7fe\ua7ff\ua82c\ua82d\ua82e\ua82f\ua830\ua831\ua832\ua833\ua834\ua835\ua836\ua837\ua838\ua839\ua83a\ua83b\ua83c\ua83d\ua83e\ua83f\ua840\ua841\ua842\ua843\ua844\ua845\ua846\ua847\ua848\ua849\ua84a\ua84b\ua84c\ua84d\ua84e\ua84f\ua850\ua851\ua852\ua853\ua854\ua855\ua856\ua857\ua858\ua859\ua85a\ua85b\ua85c\ua85d\ua85e\ua85f\ua860\ua861\ua862\ua863\ua864\ua865\ua866\ua867\ua868\ua869\ua86a\ua86b\ua86c\ua86d\ua86e\ua86f\ua870\ua871\ua872\ua873\ua874\ua875\ua876\ua877\ua878\ua879\ua87a\ua87b\ua87c\ua87d\ua87e\ua87f\ua880\ua881\ua882\ua883\ua884\ua885
 \ua886\ua887\ua888\ua889\ua88a\ua88b\ua88c\ua88d\ua88e\ua88f\ua890\ua891\ua892\ua893\ua894\ua895\ua896\ua897\ua898\ua899\ua89a\ua89b\ua89c\ua89d\ua89e\ua89f\ua8a0\ua8a1\ua8a2\ua8a3\ua8a4\ua8a5\ua8a6\ua8a7\ua8a8\ua8a9\ua8aa\ua8ab\ua8ac\ua8ad\ua8ae\ua8af\ua8b0\ua8b1\ua8b2\ua8b3\ua8b4\ua8b5\ua8b6\ua8b7\ua8b8\ua8b9\ua8ba\ua8bb\ua8bc\ua8bd\ua8be\ua8bf\ua8c0\ua8c1\ua8c2\ua8c3\ua8c4\ua8c5\ua8c6\ua8c7\ua8c8\ua8c9\ua8ca\ua8cb\ua8cc\ua8cd\ua8ce\ua8cf\ua8d0\ua8d1\ua8d2\ua8d3\ua8d4\ua8d5\ua8d6\ua8d7\ua8d8\ua8d9\ua8da\ua8db\ua8dc\ua8dd\ua8de\ua8df\ua8e0\ua8e1\ua8e2\ua8e3\ua8e4\ua8e5\ua8e6\ua8e7\ua8e8\ua8e9\ua8ea\ua8eb\ua8ec\ua8ed\ua8ee\ua8ef\ua8f0\ua8f1\ua8f2\ua8f3\ua8f4\ua8f5\ua8f6\ua8f7\ua8f8\ua8f9\ua8fa\ua8fb\ua8fc\ua8fd\ua8fe\ua8ff\ua900\ua901\ua902\ua903\ua904\ua905\ua906\ua907\ua908\ua909\ua90a\ua90b\ua90c\ua90d\ua90e\ua90f\ua910\ua911\ua912\ua913\ua914\ua915\ua916\ua917\ua918\ua919\ua91a\ua91b\ua91c\ua91d\ua91e\ua91f\ua920\ua921\ua922\ua923\ua924\ua925\ua926\ua927\ua928\ua929\ua92a\ua92b\
 ua92c\ua92d\ua92e\ua92f\ua930\ua931\ua932\ua933\ua934\ua935\ua936\ua937\ua938\ua939\ua93a\ua93b\ua93c\ua93d\ua93e\ua93f\ua940\ua941\ua942\ua943\ua944\ua945\ua946\ua947\ua948\ua949\ua94a\ua94b\ua94c\ua94d\ua94e\ua94f\ua950\ua951\ua952\ua953\ua954\ua955\ua956\ua957\ua958\ua959\ua95a\ua95b\ua95c\ua95d\ua95e\ua95f\ua960\ua961\ua962\ua963\ua964\ua965\ua966\ua967\ua968\ua969\ua96a\ua96b\ua96c\ua96d\ua96e\ua96f\ua970\ua971\ua972\ua973\ua974\ua975\ua976\ua977\ua978\ua979\ua97a\ua97b\ua97c\ua97d\ua97e\ua97f\ua980\ua981\ua982\ua983\ua984\ua985\ua986\ua987\ua988\ua989\ua98a\ua98b\ua98c\ua98d\ua98e\ua98f\ua990\ua991\ua992\ua993\ua994\ua995\ua996\ua997\ua998\ua999\ua99a\ua99b\ua99c\ua99d\ua99e\ua99f\ua9a0\ua9a1\ua9a2\ua9a3\ua9a4\ua9a5\ua9a6\ua9a7\ua9a8\ua9a9\ua9aa\ua9ab\ua9ac\ua9ad\ua9ae\ua9af\ua9b0\ua9b1\ua9b2\ua9b3\ua9b4\ua9b5\ua9b6\ua9b7\ua9b8\ua9b9\ua9ba\ua9bb\ua9bc\ua9bd\ua9be\ua9bf\ua9c0\ua9c1\ua9c2\ua9c3\ua9c4\ua9c5\ua9c6\ua9c7\ua9c8\ua9c9\ua9ca\ua9cb\ua9cc\ua9cd\ua9ce\ua9cf\ua9d0\ua9d1\u
 a9d2\ua9d3\ua9d4\ua9d5\ua9d6\ua9d7\ua9d8\ua9d9\ua9da\ua9db\ua9dc\ua9dd\ua9de\ua9df\ua9e0\ua9e1\ua9e2\ua9e3\ua9e4\ua9e5\ua9e6\ua9e7\ua9e8\ua9e9\ua9ea\ua9eb\ua9ec\ua9ed\ua9ee\ua9ef\ua9f0\ua9f1\ua9f2\ua9f3\ua9f4\ua9f5\ua9f6\ua9f7\ua9f8\ua9f9\ua9fa\ua9fb\ua9fc\ua9fd\ua9fe\ua9ff\uaa00\uaa01\uaa02\uaa03\uaa04\uaa05\uaa06\uaa07\uaa08\uaa09\uaa0a\uaa0b\uaa0c\uaa0d\uaa0e\uaa0f\uaa10\uaa11\uaa12\uaa13\uaa14\uaa15\uaa16\uaa17\uaa18\uaa19\uaa1a\uaa1b\uaa1c\uaa1d\uaa1e\uaa1f\uaa20\uaa21\uaa22\uaa23\uaa24\uaa25\uaa26\uaa27\uaa28\uaa29\uaa2a\uaa2b\uaa2c\uaa2d\uaa2e\uaa2f\uaa30\uaa31\uaa32\uaa33\uaa34\uaa35\uaa36\uaa37\uaa38\uaa39\uaa3a\uaa3b\uaa3c\uaa3d\uaa3e\uaa3f\uaa40\uaa41\uaa42\uaa43\uaa44\uaa45\uaa46\uaa47\uaa48\uaa49\uaa4a\uaa4b\uaa4c\uaa4d\uaa4e\uaa4f\uaa50\uaa51\uaa52\uaa53\uaa54\uaa55\uaa56\uaa57\uaa58\uaa59\uaa5a\uaa5b\uaa5c\uaa5d\uaa5e\uaa5f\uaa60\uaa61\uaa62\uaa63\uaa64\uaa65\uaa66\uaa67\uaa68\uaa69\uaa6a\uaa6b\uaa6c\uaa6d\uaa6e\uaa6f\uaa70\uaa71\uaa72\uaa73\uaa74\uaa75\uaa76\uaa77\ua
 a78\uaa79\uaa7a\uaa7b\uaa7c\uaa7d\uaa7e\uaa7f\uaa80\uaa81\uaa82\uaa83\uaa84\uaa85\uaa86\uaa87\uaa88\uaa89\uaa8a\uaa8b\uaa8c\uaa8d\uaa8e\uaa8f\uaa90\uaa91\uaa92\uaa93\uaa94\uaa95\uaa96\uaa97\uaa98\uaa99\uaa9a\uaa9b\uaa9c\uaa9d\uaa9e\uaa9f\uaaa0\uaaa1\uaaa2\uaaa3\uaaa4\uaaa5\uaaa6\uaaa7\uaaa8\uaaa9\uaaaa\uaaab\uaaac\uaaad\uaaae\uaaaf\uaab0\uaab1\uaab2\uaab3\uaab4\uaab5\uaab6\uaab7\uaab8\uaab9\uaaba\uaabb\uaabc\uaabd\uaabe\uaabf\uaac0\uaac1\uaac2\uaac3\uaac4\uaac5\uaac6\uaac7\uaac8\uaac9\uaaca\uaacb\uaacc\uaacd\uaace\uaacf\uaad0\uaad1\uaad2\uaad3\uaad4\uaad5\uaad6\uaad7\uaad8\uaad9\uaada\uaadb\uaadc\uaadd\uaade\uaadf\uaae0\uaae1\uaae2\uaae3\uaae4\uaae5\uaae6\uaae7\uaae8\uaae9\uaaea\uaaeb\uaaec\uaaed\uaaee\uaaef\uaaf0\uaaf1\uaaf2\uaaf3\uaaf4\uaaf5\uaaf6\uaaf7\uaaf8\uaaf9\uaafa\uaafb\uaafc\uaafd\uaafe\uaaff\uab00\uab01\uab02\uab03\uab04\uab05\uab06\uab07\uab08\uab09\uab0a\uab0b\uab0c\uab0d\uab0e\uab0f\uab10\uab11\uab12\uab13\uab14\uab15\uab16\uab17\uab18\uab19\uab1a\uab1b\uab1c\uab1d\uab
 1e\uab1f\uab20\uab21\uab22\uab23\uab24\uab25\uab26\uab27\uab28\uab29\uab2a\uab2b\uab2c\uab2d\uab2e\uab2f\uab30\uab31\uab32\uab33\uab34\uab35\uab36\uab37\uab38\uab39\uab3a\uab3b\uab3c\uab3d\uab3e\uab3f\uab40\uab41\uab42\uab43\uab44\uab45\uab46\uab47\uab48\uab49\uab4a\uab4b\uab4c\uab4d\uab4e\uab4f\uab50\uab51\uab52\uab53\uab54\uab55\uab56\uab57\uab58\uab59\uab5a\uab5b\uab5c\uab5d\uab5e\uab5f\uab60\uab61\uab62\uab63\uab64\uab65\uab66\uab67\uab68\uab69\uab6a\uab6b\uab6c\uab6d\uab6e\uab6f\uab70\uab71\uab72\uab73\uab74\uab75\uab76\uab77\uab78\uab79\uab7a\uab7b\uab7c\uab7d\uab7e\uab7f\uab80\uab81\uab82\uab83\uab84\uab85\uab86\uab87\uab88\uab89\uab8a\uab8b\uab8c\uab8d\uab8e\uab8f\uab90\uab91\uab92\uab93\uab94\uab95\uab96\uab97\uab98\uab99\uab9a\uab9b\uab9c\uab9d\uab9e\uab9f\uaba0\uaba1\uaba2\uaba3\uaba4\uaba5\uaba6\uaba7\uaba8\uaba9\uabaa\uabab\uabac\uabad\uabae\uabaf\uabb0\uabb1\uabb2\uabb3\uabb4\uabb5\uabb6\uabb7\uabb8\uabb9\uabba\uabbb\uabbc\uabbd\uabbe\uabbf\uabc0\uabc1\uabc2\uabc3\uabc
 4\uabc5\uabc6\uabc7\uabc8\uabc9\uabca\uabcb\uabcc\uabcd\uabce\uabcf\uabd0\uabd1\uabd2\uabd3\uabd4\uabd5\uabd6\uabd7\uabd8\uabd9\uabda\uabdb\uabdc\uabdd\uabde\uabdf\uabe0\uabe1\uabe2\uabe3\uabe4\uabe5\uabe6\uabe7\uabe8\uabe9\uabea\uabeb\uabec\uabed\uabee\uabef\uabf0\uabf1\uabf2\uabf3\uabf4\uabf5\uabf6\uabf7\uabf8\uabf9\uabfa\uabfb\uabfc\uabfd\uabfe\uabff\ud7a4\ud7a5\ud7a6\ud7a7\ud7a8\ud7a9\ud7aa\ud7ab\ud7ac\ud7ad\ud7ae\ud7af\ud7b0\ud7b1\ud7b2\ud7b3\ud7b4\ud7b5\ud7b6\ud7b7\ud7b8\ud7b9\ud7ba\ud7bb\ud7bc\ud7bd\ud7be\ud7bf\ud7c0\ud7c1\ud7c2\ud7c3\ud7c4\ud7c5\ud7c6\ud7c7\ud7c8\ud7c9\ud7ca\ud7cb\ud7cc\ud7cd\ud7ce\ud7cf\ud7d0\ud7d1\ud7d2\ud7d3\ud7d4\ud7d5\ud7d6\ud7d7\ud7d8\ud7d9\ud7da\ud7db\ud7dc\ud7dd\ud7de\ud7df\ud7e0\ud7e1\ud7e2\ud7e3\ud7e4\ud7e5\ud7e6\ud7e7\ud7e8\ud7e9\ud7ea\ud7eb\ud7ec\ud7ed\ud7ee\ud7ef\ud7f0\ud7f1\ud7f2\ud7f3\ud7f4\ud7f5\ud7f6\ud7f7\ud7f8\ud7f9\ud7fa\ud7fb\ud7fc\ud7fd\ud7fe\ud7ff\ufa2e\ufa2f\ufa6b\ufa6c\ufa6d\ufa6e\ufa6f\ufada\ufadb\ufadc\ufadd\ufade\ufadf\ufae0\ufae1
 \ufae2\ufae3\ufae4\ufae5\ufae6\ufae7\ufae8\ufae9\ufaea\ufaeb\ufaec\ufaed\ufaee\ufaef\ufaf0\ufaf1\ufaf2\ufaf3\ufaf4\ufaf5\ufaf6\ufaf7\ufaf8\ufaf9\ufafa\ufafb\ufafc\ufafd\ufafe\ufaff\ufb07\ufb08\ufb09\ufb0a\ufb0b\ufb0c\ufb0d\ufb0e\ufb0f\ufb10\ufb11\ufb12\ufb18\ufb19\ufb1a\ufb1b\ufb1c\ufb37\ufb3d\ufb3f\ufb42\ufb45\ufbb2\ufbb3\ufbb4\ufbb5\ufbb6\ufbb7\ufbb8\ufbb9\ufbba\ufbbb\ufbbc\ufbbd\ufbbe\ufbbf\ufbc0\ufbc1\ufbc2\ufbc3\ufbc4\ufbc5\ufbc6\ufbc7\ufbc8\ufbc9\ufbca\ufbcb\ufbcc\ufbcd\ufbce\ufbcf\ufbd0\ufbd1\ufbd2\ufd40\ufd41\ufd42\ufd43\ufd44\ufd45\ufd46\ufd47\ufd48\ufd49\ufd4a\ufd4b\ufd4c\ufd4d\ufd4e\ufd4f\ufd90\ufd91\ufdc8\ufdc9\ufdca\ufdcb\ufdcc\ufdcd\ufdce\ufdcf\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea\ufdeb\ufdec\ufded\ufdee\ufdef\ufdfe\ufdff\ufe1a\ufe1b\ufe1c\ufe1d\ufe1e\ufe1f\ufe24\ufe25\ufe26\ufe27\ufe28\ufe29\ufe2a\ufe2b\ufe2c\ufe2d\ufe2e\ufe2f\ufe53\ufe67\ufe6c\
 ufe6d\ufe6e\ufe6f\ufe75\ufefd\ufefe\uff00\uffbf\uffc0\uffc1\uffc8\uffc9\uffd0\uffd1\uffd8\uffd9\uffdd\uffde\uffdf\uffe7\uffef\ufff0\ufff1\ufff2\ufff3\ufff4\ufff5\ufff6\ufff7\ufff8\ufffe'
-
-Co = u'\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009\ue00a\ue00b\ue00c\ue00d\ue00e\ue00f\ue010\ue011\ue012\ue013\ue014\ue015\ue016\ue017\ue018\ue019\ue01a\ue01b\ue01c\ue01d\ue01e\ue01f\ue020\ue021\ue022\ue023\ue024\ue025\ue026\ue027\ue028\ue029\ue02a\ue02b\ue02c\ue02d\ue02e\ue02f\ue030\ue031\ue032\ue033\ue034\ue035\ue036\ue037\ue038\ue039\ue03a\ue03b\ue03c\ue03d\ue03e\ue03f\ue040\ue041\ue042\ue043\ue044\ue045\ue046\ue047\ue048\ue049\ue04a\ue04b\ue04c\ue04d\ue04e\ue04f\ue050\ue051\ue052\ue053\ue054\ue055\ue056\ue057\ue058\ue059\ue05a\ue05b\ue05c\ue05d\ue05e\ue05f\ue060\ue061\ue062\ue063\ue064\ue065\ue066\ue067\ue068\ue069\ue06a\ue06b\ue06c\ue06d\ue06e\ue06f\ue070\ue071\ue072\ue073\ue074\ue075\ue076\ue077\ue078\ue079\ue07a\ue07b\ue07c\ue07d\ue07e\ue07f\ue080\ue081\ue082\ue083\ue084\ue085\ue086\ue087\ue088\ue089\ue08a\ue08b\ue08c\ue08d\ue08e\ue08f\ue090\ue091\ue092\ue093\ue094\ue095\ue096\ue097\ue098\ue099\ue09a\ue09b\ue09c\ue09d\ue09e\ue09f\ue0a0\ue0a1\ue0a2\ue0a3\ue0a4
 \ue0a5\ue0a6\ue0a7\ue0a8\ue0a9\ue0aa\ue0ab\ue0ac\ue0ad\ue0ae\ue0af\ue0b0\ue0b1\ue0b2\ue0b3\ue0b4\ue0b5\ue0b6\ue0b7\ue0b8\ue0b9\ue0ba\ue0bb\ue0bc\ue0bd\ue0be\ue0bf\ue0c0\ue0c1\ue0c2\ue0c3\ue0c4\ue0c5\ue0c6\ue0c7\ue0c8\ue0c9\ue0ca\ue0cb\ue0cc\ue0cd\ue0ce\ue0cf\ue0d0\ue0d1\ue0d2\ue0d3\ue0d4\ue0d5\ue0d6\ue0d7\ue0d8\ue0d9\ue0da\ue0db\ue0dc\ue0dd\ue0de\ue0df\ue0e0\ue0e1\ue0e2\ue0e3\ue0e4\ue0e5\ue0e6\ue0e7\ue0e8\ue0e9\ue0ea\ue0eb\ue0ec\ue0ed\ue0ee\ue0ef\ue0f0\ue0f1\ue0f2\ue0f3\ue0f4\ue0f5\ue0f6\ue0f7\ue0f8\ue0f9\ue0fa\ue0fb\ue0fc\ue0fd\ue0fe\ue0ff\ue100\ue101\ue102\ue103\ue104\ue105\ue106\ue107\ue108\ue109\ue10a\ue10b\ue10c\ue10d\ue10e\ue10f\ue110\ue111\ue112\ue113\ue114\ue115\ue116\ue117\ue118\ue119\ue11a\ue11b\ue11c\ue11d\ue11e\ue11f\ue120\ue121\ue122\ue123\ue124\ue125\ue126\ue127\ue128\ue129\ue12a\ue12b\ue12c\ue12d\ue12e\ue12f\ue130\ue131\ue132\ue133\ue134\ue135\ue136\ue137\ue138\ue139\ue13a\ue13b\ue13c\ue13d\ue13e\ue13f\ue140\ue141\ue142\ue143\ue144\ue145\ue146\ue147\ue148\ue149\ue14a\
 ue14b\ue14c\ue14d\ue14e\ue14f\ue150\ue151\ue152\ue153\ue154\ue155\ue156\ue157\ue158\ue159\ue15a\ue15b\ue15c\ue15d\ue15e\ue15f\ue160\ue161\ue162\ue163\ue164\ue165\ue166\ue167\ue168\ue169\ue16a\ue16b\ue16c\ue16d\ue16e\ue16f\ue170\ue171\ue172\ue173\ue174\ue175\ue176\ue177\ue178\ue179\ue17a\ue17b\ue17c\ue17d\ue17e\ue17f\ue180\ue181\ue182\ue183\ue184\ue185\ue186\ue187\ue188\ue189\ue18a\ue18b\ue18c\ue18d\ue18e\ue18f\ue190\ue191\ue192\ue193\ue194\ue195\ue196\ue197\ue198\ue199\ue19a\ue19b\ue19c\ue19d\ue19e\ue19f\ue1a0\ue1a1\ue1a2\ue1a3\ue1a4\ue1a5\ue1a6\ue1a7\ue1a8\ue1a9\ue1aa\ue1ab\ue1ac\ue1ad\ue1ae\ue1af\ue1b0\ue1b1\ue1b2\ue1b3\ue1b4\ue1b5\ue1b6\ue1b7\ue1b8\ue1b9\ue1ba\ue1bb\ue1bc\ue1bd\ue1be\ue1bf\ue1c0\ue1c1\ue1c2\ue1c3\ue1c4\ue1c5\ue1c6\ue1c7\ue1c8\ue1c9\ue1ca\ue1cb\ue1cc\ue1cd\ue1ce\ue1cf\ue1d0\ue1d1\ue1d2\ue1d3\ue1d4\ue1d5\ue1d6\ue1d7\ue1d8\ue1d9\ue1da\ue1db\ue1dc\ue1dd\ue1de\ue1df\ue1e0\ue1e1\ue1e2\ue1e3\ue1e4\ue1e5\ue1e6\ue1e7\ue1e8\ue1e9\ue1ea\ue1eb\ue1ec\ue1ed\ue1ee\ue1ef\ue1f0\u
 e1f1\ue1f2\ue1f3\ue1f4\ue1f5\ue1f6\ue1f7\ue1f8\ue1f9\ue1fa\ue1fb\ue1fc\ue1fd\ue1fe\ue1ff\ue200\ue201\ue202\ue203\ue204\ue205\ue206\ue207\ue208\ue209\ue20a\ue20b\ue20c\ue20d\ue20e\ue20f\ue210\ue211\ue212\ue213\ue214\ue215\ue216\ue217\ue218\ue219\ue21a\ue21b\ue21c\ue21d\ue21e\ue21f\ue220\ue221\ue222\ue223\ue224\ue225\ue226\ue227\ue228\ue229\ue22a\ue22b\ue22c\ue22d\ue22e\ue22f\ue230\ue231\ue232\ue233\ue234\ue235\ue236\ue237\ue238\ue239\ue23a\ue23b\ue23c\ue23d\ue23e\ue23f\ue240\ue241\ue242\ue243\ue244\ue245\ue246\ue247\ue248\ue249\ue24a\ue24b\ue24c\ue24d\ue24e\ue24f\ue250\ue251\ue252\ue253\ue254\ue255\ue256\ue257\ue258\ue259\ue25a\ue25b\ue25c\ue25d\ue25e\ue25f\ue260\ue261\ue262\ue263\ue264\ue265\ue266\ue267\ue268\ue269\ue26a\ue26b\ue26c\ue26d\ue26e\ue26f\ue270\ue271\ue272\ue273\ue274\ue275\ue276\ue277\ue278\ue279\ue27a\ue27b\ue27c\ue27d\ue27e\ue27f\ue280\ue281\ue282\ue283\ue284\ue285\ue286\ue287\ue288\ue289\ue28a\ue28b\ue28c\ue28d\ue28e\ue28f\ue290\ue291\ue292\ue293\ue294\ue295\ue296\ue
 297\ue298\ue299\ue29a\ue29b\ue29c\ue29d\ue29e\ue29f\ue2a0\ue2a1\ue2a2\ue2a3\ue2a4\ue2a5\ue2a6\ue2a7\ue2a8\ue2a9\ue2aa\ue2ab\ue2ac\ue2ad\ue2ae\ue2af\ue2b0\ue2b1\ue2b2\ue2b3\ue2b4\ue2b5\ue2b6\ue2b7\ue2b8\ue2b9\ue2ba\ue2bb\ue2bc\ue2bd\ue2be\ue2bf\ue2c0\ue2c1\ue2c2\ue2c3\ue2c4\ue2c5\ue2c6\ue2c7\ue2c8\ue2c9\ue2ca\ue2cb\ue2cc\ue2cd\ue2ce\ue2cf\ue2d0\ue2d1\ue2d2\ue2d3\ue2d4\ue2d5\ue2d6\ue2d7\ue2d8\ue2d9\ue2da\ue2db\ue2dc\ue2dd\ue2de\ue2df\ue2e0\ue2e1\ue2e2\ue2e3\ue2e4\ue2e5\ue2e6\ue2e7\ue2e8\ue2e9\ue2ea\ue2eb\ue2ec\ue2ed\ue2ee\ue2ef\ue2f0\ue2f1\ue2f2\ue2f3\ue2f4\ue2f5\ue2f6\ue2f7\ue2f8\ue2f9\ue2fa\ue2fb\ue2fc\ue2fd\ue2fe\ue2ff\ue300\ue301\ue302\ue303\ue304\ue305\ue306\ue307\ue308\ue309\ue30a\ue30b\ue30c\ue30d\ue30e\ue30f\ue310\ue311\ue312\ue313\ue314\ue315\ue316\ue317\ue318\ue319\ue31a\ue31b\ue31c\ue31d\ue31e\ue31f\ue320\ue321\ue322\ue323\ue324\ue325\ue326\ue327\ue328\ue329\ue32a\ue32b\ue32c\ue32d\ue32e\ue32f\ue330\ue331\ue332\ue333\ue334\ue335\ue336\ue337\ue338\ue339\ue33a\ue33b\ue33c\ue3
 3d\ue33e\ue33f\ue340\ue341\ue342\ue343\ue344\ue345\ue346\ue347\ue348\ue349\ue34a\ue34b\ue34c\ue34d\ue34e\ue34f\ue350\ue351\ue352\ue353\ue354\ue355\ue356\ue357\ue358\ue359\ue35a\ue35b\ue35c\ue35d\ue35e\ue35f\ue360\ue361\ue362\ue363\ue364\ue365\ue366\ue367\ue368\ue369\ue36a\ue36b\ue36c\ue36d\ue36e\ue36f\ue370\ue371\ue372\ue373\ue374\ue375\ue376\ue377\ue378\ue379\ue37a\ue37b\ue37c\ue37d\ue37e\ue37f\ue380\ue381\ue382\ue383\ue384\ue385\ue386\ue387\ue388\ue389\ue38a\ue38b\ue38c\ue38d\ue38e\ue38f\ue390\ue391\ue392\ue393\ue394\ue395\ue396\ue397\ue398\ue399\ue39a\ue39b\ue39c\ue39d\ue39e\ue39f\ue3a0\ue3a1\ue3a2\ue3a3\ue3a4\ue3a5\ue3a6\ue3a7\ue3a8\ue3a9\ue3aa\ue3ab\ue3ac\ue3ad\ue3ae\ue3af\ue3b0\ue3b1\ue3b2\ue3b3\ue3b4\ue3b5\ue3b6\ue3b7\ue3b8\ue3b9\ue3ba\ue3bb\ue3bc\ue3bd\ue3be\ue3bf\ue3c0\ue3c1\ue3c2\ue3c3\ue3c4\ue3c5\ue3c6\ue3c7\ue3c8\ue3c9\ue3ca\ue3cb\ue3cc\ue3cd\ue3ce\ue3cf\ue3d0\ue3d1\ue3d2\ue3d3\ue3d4\ue3d5\ue3d6\ue3d7\ue3d8\ue3d9\ue3da\ue3db\ue3dc\ue3dd\ue3de\ue3df\ue3e0\ue3e1\ue3e2\ue3e
 3\ue3e4\ue3e5\ue3e6\ue3e7\ue3e8\ue3e9\ue3ea\ue3eb\ue3ec\ue3ed\ue3ee\ue3ef\ue3f0\ue3f1\ue3f2\ue3f3\ue3f4\ue3f5\ue3f6\ue3f7\ue3f8\ue3f9\ue3fa\ue3fb\ue3fc\ue3fd\ue3fe\ue3ff\ue400\ue401\ue402\ue403\ue404\ue405\ue406\ue407\ue408\ue409\ue40a\ue40b\ue40c\ue40d\ue40e\ue40f\ue410\ue411\ue412\ue413\ue414\ue415\ue416\ue417\ue418\ue419\ue41a\ue41b\ue41c\ue41d\ue41e\ue41f\ue420\ue421\ue422\ue423\ue424\ue425\ue426\ue427\ue428\ue429\ue42a\ue42b\ue42c\ue42d\ue42e\ue42f\ue430\ue431\ue432\ue433\ue434\ue435\ue436\ue437\ue438\ue439\ue43a\ue43b\ue43c\ue43d\ue43e\ue43f\ue440\ue441\ue442\ue443\ue444\ue445\ue446\ue447\ue448\ue449\ue44a\ue44b\ue44c\ue44d\ue44e\ue44f\ue450\ue451\ue452\ue453\ue454\ue455\ue456\ue457\ue458\ue459\ue45a\ue45b\ue45c\ue45d\ue45e\ue45f\ue460\ue461\ue462\ue463\ue464\ue465\ue466\ue467\ue468\ue469\ue46a\ue46b\ue46c\ue46d\ue46e\ue46f\ue470\ue471\ue472\ue473\ue474\ue475\ue476\ue477\ue478\ue479\ue47a\ue47b\ue47c\ue47d\ue47e\ue47f\ue480\ue481\ue482\ue483\ue484\ue485\ue486\ue487\ue488\ue489
 \ue48a\ue48b\ue48c\ue48d\ue48e\ue48f\ue490\ue491\ue492\ue493\ue494\ue495\ue496\ue497\ue498\ue499\ue49a\ue49b\ue49c\ue49d\ue49e\ue49f\ue4a0\ue4a1\ue4a2\ue4a3\ue4a4\ue4a5\ue4a6\ue4a7\ue4a8\ue4a9\ue4aa\ue4ab\ue4ac\ue4ad\ue4ae\ue4af\ue4b0\ue4b1\ue4b2\ue4b3\ue4b4\ue4b5\ue4b6\ue4b7\ue4b8\ue4b9\ue4ba\ue4bb\ue4bc\ue4bd\ue4be\ue4bf\ue4c0\ue4c1\ue4c2\ue4c3\ue4c4\ue4c5\ue4c6\ue4c7\ue4c8\ue4c9\ue4ca\ue4cb\ue4cc\ue4cd\ue4ce\ue4cf\ue4d0\ue4d1\ue4d2\ue4d3\ue4d4\ue4d5\ue4d6\ue4d7\ue4d8\ue4d9\ue4da\ue4db\ue4dc\ue4dd\ue4de\ue4df\ue4e0\ue4e1\ue4e2\ue4e3\ue4e4\ue4e5\ue4e6\ue4e7\ue4e8\ue4e9\ue4ea\ue4eb\ue4ec\ue4ed\ue4ee\ue4ef\ue4f0\ue4f1\ue4f2\ue4f3\ue4f4\ue4f5\ue4f6\ue4f7\ue4f8\ue4f9\ue4fa\ue4fb\ue4fc\ue4fd\ue4fe\ue4ff\ue500\ue501\ue502\ue503\ue504\ue505\ue506\ue507\ue508\ue509\ue50a\ue50b\ue50c\ue50d\ue50e\ue50f\ue510\ue511\ue512\ue513\ue514\ue515\ue516\ue517\ue518\ue519\ue51a\ue51b\ue51c\ue51d\ue51e\ue51f\ue520\ue521\ue522\ue523\ue524\ue525\ue526\ue527\ue528\ue529\ue52a\ue52b\ue52c\ue52d\ue52e\ue52f\
 ue530\ue531\ue532\ue533\ue534\ue535\ue536\ue537\ue538\ue539\ue53a\ue53b\ue53c\ue53d\ue53e\ue53f\ue540\ue541\ue542\ue543\ue544\ue545\ue546\ue547\ue548\ue549\ue54a\ue54b\ue54c\ue54d\ue54e\ue54f\ue550\ue551\ue552\ue553\ue554\ue555\ue556\ue557\ue558\ue559\ue55a\ue55b\ue55c\ue55d\ue55e\ue55f\ue560\ue561\ue562\ue563\ue564\ue565\ue566\ue567\ue568\ue569\ue56a\ue56b\ue56c\ue56d\ue56e\ue56f\ue570\ue571\ue572\ue573\ue574\ue575\ue576\ue577\ue578\ue579\ue57a\ue57b\ue57c\ue57d\ue57e\ue57f\ue580\ue581\ue582\ue583\ue584\ue585\ue586\ue587\ue588\ue589\ue58a\ue58b\ue58c\ue58d\ue58e\ue58f\ue590\ue591\ue592\ue593\ue594\ue595\ue596\ue597\ue598\ue599\ue59a\ue59b\ue59c\ue59d\ue59e\ue59f\ue5a0\ue5a1\ue5a2\ue5a3\ue5a4\ue5a5\ue5a6\ue5a7\ue5a8\ue5a9\ue5aa\ue5ab\ue5ac\ue5ad\ue5ae\ue5af\ue5b0\ue5b1\ue5b2\ue5b3\ue5b4\ue5b5\ue5b6\ue5b7\ue5b8\ue5b9\ue5ba\ue5bb\ue5bc\ue5bd\ue5be\ue5bf\ue5c0\ue5c1\ue5c2\ue5c3\ue5c4\ue5c5\ue5c6\ue5c7\ue5c8\ue5c9\ue5ca\ue5cb\ue5cc\ue5cd\ue5ce\ue5cf\ue5d0\ue5d1\ue5d2\ue5d3\ue5d4\ue5d5\u
 e5d6\ue5d7\ue5d8\ue5d9\ue5da\ue5db\ue5dc\ue5dd\ue5de\ue5df\ue5e0\ue5e1\ue5e2\ue5e3\ue5e4\ue5e5\ue5e6\ue5e7\ue5e8\ue5e9\ue5ea\ue5eb\ue5ec\ue5ed\ue5ee\ue5ef\ue5f0\ue5f1\ue5f2\ue5f3\ue5f4\ue5f5\ue5f6\ue5f7\ue5f8\ue5f9\ue5fa\ue5fb\ue5fc\ue5fd\ue5fe\ue5ff\ue600\ue601\ue602\ue603\ue604\ue605\ue606\ue607\ue608\ue609\ue60a\ue60b\ue60c\ue60d\ue60e\ue60f\ue610\ue611\ue612\ue613\ue614\ue615\ue616\ue617\ue618\ue619\ue61a\ue61b\ue61c\ue61d\ue61e\ue61f\ue620\ue621\ue622\ue623\ue624\ue625\ue626\ue627\ue628\ue629\ue62a\ue62b\ue62c\ue62d\ue62e\ue62f\ue630\ue631\ue632\ue633\ue634\ue635\ue636\ue637\ue638\ue639\ue63a\ue63b\ue63c\ue63d\ue63e\ue63f\ue640\ue641\ue642\ue643\ue644\ue645\ue646\ue647\ue648\ue649\ue64a\ue64b\ue64c\ue64d\ue64e\ue64f\ue650\ue651\ue652\ue653\ue654\ue655\ue656\ue657\ue658\ue659\ue65a\ue65b\ue65c\ue65d\ue65e\ue65f\ue660\ue661\ue662\ue663\ue664\ue665\ue666\ue667\ue668\ue669\ue66a\ue66b\ue66c\ue66d\ue66e\ue66f\ue670\ue671\ue672\ue673\ue674\ue675\ue676\ue677\ue678\ue679\ue67a\ue67b\ue
 67c\ue67d\ue67e\ue67f\ue680\ue681\ue682\ue683\ue684\ue685\ue686\ue687\ue688\ue689\ue68a\ue68b\ue68c\ue68d\ue68e\ue68f\ue690\ue691\ue692\ue693\ue694\ue695\ue696\ue697\ue698\ue699\ue69a\ue69b\ue69c\ue69d\ue69e\ue69f\ue6a0\ue6a1\ue6a2\ue6a3\ue6a4\ue6a5\ue6a6\ue6a7\ue6a8\ue6a9\ue6aa\ue6ab\ue6ac\ue6ad\ue6ae\ue6af\ue6b0\ue6b1\ue6b2\ue6b3\ue6b4\ue6b5\ue6b6\ue6b7\ue6b8\ue6b9\ue6ba\ue6bb\ue6bc\ue6bd\ue6be\ue6bf\ue6c0\ue6c1\ue6c2\ue6c3\ue6c4\ue6c5\ue6c6\ue6c7\ue6c8\ue6c9\ue6ca\ue6cb\ue6cc\ue6cd\ue6ce\ue6cf\ue6d0\ue6d1\ue6d2\ue6d3\ue6d4\ue6d5\ue6d6\ue6d7\ue6d8\ue6d9\ue6da\ue6db\ue6dc\ue6dd\ue6de\ue6df\ue6e0\ue6e1\ue6e2\ue6e3\ue6e4\ue6e5\ue6e6\ue6e7\ue6e8\ue6e9\ue6ea\ue6eb\ue6ec\ue6ed\ue6ee\ue6ef\ue6f0\ue6f1\ue6f2\ue6f3\ue6f4\ue6f5\ue6f6\ue6f7\ue6f8\ue6f9\ue6fa\ue6fb\ue6fc\ue6fd\ue6fe\ue6ff\ue700\ue701\ue702\ue703\ue704\ue705\ue706\ue707\ue708\ue709\ue70a\ue70b\ue70c\ue70d\ue70e\ue70f\ue710\ue711\ue712\ue713\ue714\ue715\ue716\ue717\ue718\ue719\ue71a\ue71b\ue71c\ue71d\ue71e\ue71f\ue720\ue721\ue7
 22\ue723\ue724\ue725\ue726\ue727\ue728\ue729\ue72a\ue72b\ue72c\ue72d\ue72e\ue72f\ue730\ue731\ue732\ue733\ue734\ue735\ue736\ue737\ue738\ue739\ue73a\ue73b\ue73c\ue73d\ue73e\ue73f\ue740\ue741\ue742\ue743\ue744\ue745\ue746\ue747\ue748\ue749\ue74a\ue74b\ue74c\ue74d\ue74e\ue74f\ue750\ue751\ue752\ue753\ue754\ue755\ue756\ue757\ue758\ue759\ue75a\ue75b\ue75c\ue75d\ue75e\ue75f\ue760\ue761\ue762\ue763\ue764\ue765\ue766\ue767\ue768\ue769\ue76a\ue76b\ue76c\ue76d\ue76e\ue76f\ue770\ue771\ue772\ue773\ue774\ue775\ue776\ue777\ue778\ue779\ue77a\ue77b\ue77c\ue77d\ue77e\ue77f\ue780\ue781\ue782\ue783\ue784\ue785\ue786\ue787\ue788\ue789\ue78a\ue78b\ue78c\ue78d\ue78e\ue78f\ue790\ue791\ue792\ue793\ue794\ue795\ue796\ue797\ue798\ue799\ue79a\ue79b\ue79c\ue79d\ue79e\ue79f\ue7a0\ue7a1\ue7a2\ue7a3\ue7a4\ue7a5\ue7a6\ue7a7\ue7a8\ue7a9\ue7aa\ue7ab\ue7ac\ue7ad\ue7ae\ue7af\ue7b0\ue7b1\ue7b2\ue7b3\ue7b4\ue7b5\ue7b6\ue7b7\ue7b8\ue7b9\ue7ba\ue7bb\ue7bc\ue7bd\ue7be\ue7bf\ue7c0\ue7c1\ue7c2\ue7c3\ue7c4\ue7c5\ue7c6\ue7c7\ue7c
 8\ue7c9\ue7ca\ue7cb\ue7cc\ue7cd\ue7ce\ue7cf\ue7d0\ue7d1\ue7d2\ue7d3\ue7d4\ue7d5\ue7d6\ue7d7\ue7d8\ue7d9\ue7da\ue7db\ue7dc\ue7dd\ue7de\ue7df\ue7e0\ue7e1\ue7e2\ue7e3\ue7e4\ue7e5\ue7e6\ue7e7\ue7e8\ue7e9\ue7ea\ue7eb\ue7ec\ue7ed\ue7ee\ue7ef\ue7f0\ue7f1\ue7f2\ue7f3\ue7f4\ue7f5\ue7f6\ue7f7\ue7f8\ue7f9\ue7fa\ue7fb\ue7fc\ue7fd\ue7fe\ue7ff\ue800\ue801\ue802\ue803\ue804\ue805\ue806\ue807\ue808\ue809\ue80a\ue80b\ue80c\ue80d\ue80e\ue80f\ue810\ue811\ue812\ue813\ue814\ue815\ue816\ue817\ue818\ue819\ue81a\ue81b\ue81c\ue81d\ue81e\ue81f\ue820\ue821\ue822\ue823\ue824\ue825\ue826\ue827\ue828\ue829\ue82a\ue82b\ue82c\ue82d\ue82e\ue82f\ue830\ue831\ue832\ue833\ue834\ue835\ue836\ue837\ue838\ue839\ue83a\ue83b\ue83c\ue83d\ue83e\ue83f\ue840\ue841\ue842\ue843\ue844\ue845\ue846\ue847\ue848\ue849\ue84a\ue84b\ue84c\ue84d\ue84e\ue84f\ue850\ue851\ue852\ue853\ue854\ue855\ue856\ue857\ue858\ue859\ue85a\ue85b\ue85c\ue85d\ue85e\ue85f\ue860\ue861\ue862\ue863\ue864\ue865\ue866\ue867\ue868\ue869\ue86a\ue86b\ue86c\ue86d\ue86e
 \ue86f\ue870\ue871\ue872\ue873\ue874\ue875\ue876\ue877\ue878\ue879\ue87a\ue87b\ue87c\ue87d\ue87e\ue87f\ue880\ue881\ue882\ue883\ue884\ue885\ue886\ue887\ue888\ue889\ue88a\ue88b\ue88c\ue88d\ue88e\ue88f\ue890\ue891\ue892\ue893\ue894\ue895\ue896\ue897\ue898\ue899\ue89a\ue89b\ue89c\ue89d\ue89e\ue89f\ue8a0\ue8a1\ue8a2\ue8a3\ue8a4\ue8a5\ue8a6\ue8a7\ue8a8\ue8a9\ue8aa\ue8ab\ue8ac\ue8ad\ue8ae\ue8af\ue8b0\ue8b1\ue8b2\ue8b3\ue8b4\ue8b5\ue8b6\ue8b7\ue8b8\ue8b9\ue8ba\ue8bb\ue8bc\ue8bd\ue8be\ue8bf\ue8c0\ue8c1\ue8c2\ue8c3\ue8c4\ue8c5\ue8c6\ue8c7\ue8c8\ue8c9\ue8ca\ue8cb\ue8cc\ue8cd\ue8ce\ue8cf\ue8d0\ue8d1\ue8d2\ue8d3\ue8d4\ue8d5\ue8d6\ue8d7\ue8d8\ue8d9\ue8da\ue8db\ue8dc\ue8dd\ue8de\ue8df\ue8e0\ue8e1\ue8e2\ue8e3\ue8e4\ue8e5\ue8e6\ue8e7\ue8e8\ue8e9\ue8ea\ue8eb\ue8ec\ue8ed\ue8ee\ue8ef\ue8f0\ue8f1\ue8f2\ue8f3\ue8f4\ue8f5\ue8f6\ue8f7\ue8f8\ue8f9\ue8fa\ue8fb\ue8fc\ue8fd\ue8fe\ue8ff\ue900\ue901\ue902\ue903\ue904\ue905\ue906\ue907\ue908\ue909\ue90a\ue90b\ue90c\ue90d\ue90e\ue90f\ue910\ue911\ue912\ue913\ue914\
 ue915\ue916\ue917\ue918\ue919\ue91a\ue91b\ue91c\ue91d\ue91e\ue91f\ue920\ue921\ue922\ue923\ue924\ue925\ue926\ue927\ue928\ue929\ue92a\ue92b\ue92c\ue92d\ue92e\ue92f\ue930\ue931\ue932\ue933\ue934\ue935\ue936\ue937\ue938\ue939\ue93a\ue93b\ue93c\ue93d\ue93e\ue93f\ue940\ue941\ue942\ue943\ue944\ue945\ue946\ue947\ue948\ue949\ue94a\ue94b\ue94c\ue94d\ue94e\ue94f\ue950\ue951\ue952\ue953\ue954\ue955\ue956\ue957\ue958\ue959\ue95a\ue95b\ue95c\ue95d\ue95e\ue95f\ue960\ue961\ue962\ue963\ue964\ue965\ue966\ue967\ue968\ue969\ue96a\ue96b\ue96c\ue96d\ue96e\ue96f\ue970\ue971\ue972\ue973\ue974\ue975\ue976\ue977\ue978\ue979\ue97a\ue97b\ue97c\ue97d\ue97e\ue97f\ue980\ue981\ue982\ue983\ue984\ue985\ue986\ue987\ue988\ue989\ue98a\ue98b\ue98c\ue98d\ue98e\ue98f\ue990\ue991\ue992\ue993\ue994\ue995\ue996\ue997\ue998\ue999\ue99a\ue99b\ue99c\ue99d\ue99e\ue99f\ue9a0\ue9a1\ue9a2\ue9a3\ue9a4\ue9a5\ue9a6\ue9a7\ue9a8\ue9a9\ue9aa\ue9ab\ue9ac\ue9ad\ue9ae\ue9af\ue9b0\ue9b1\ue9b2\ue9b3\ue9b4\ue9b5\ue9b6\ue9b7\ue9b8\ue9b9\ue9ba\u
 e9bb\ue9bc\ue9bd\ue9be\ue9bf\ue9c0\ue9c1\ue9c2\ue9c3\ue9c4\ue9c5\ue9c6\ue9c7\ue9c8\ue9c9\ue9ca\ue9cb\ue9cc\ue9cd\ue9ce\ue9cf\ue9d0\ue9d1\ue9d2\ue9d3\ue9d4\ue9d5\ue9d6\ue9d7\ue9d8\ue9d9\ue9da\ue9db\ue9dc\ue9dd\ue9de\ue9df\ue9e0\ue9e1\ue9e2\ue9e3\ue9e4\ue9e5\ue9e6\ue9e7\ue9e8\ue9e9\ue9ea\ue9eb\ue9ec\ue9ed\ue9ee\ue9ef\ue9f0\ue9f1\ue9f2\ue9f3\ue9f4\ue9f5\ue9f6\ue9f7\ue9f8\ue9f9\ue9fa\ue9fb\ue9fc\ue9fd\ue9fe\ue9ff\uea00\uea01\uea02\uea03\uea04\uea05\uea06\uea07\uea08\uea09\uea0a\uea0b\uea0c\uea0d\uea0e\uea0f\uea10\uea11\uea12\uea13\uea14\uea15\uea16\uea17\uea18\uea19\uea1a\uea1b\uea1c\uea1d\uea1e\uea1f\uea20\uea21\uea22\uea23\uea24\uea25\uea26\uea27\uea28\uea29\uea2a\uea2b\uea2c\uea2d\uea2e\uea2f\uea30\uea31\uea32\uea33\uea34\uea35\uea36\uea37\uea38\uea39\uea3a\uea3b\uea3c\uea3d\uea3e\uea3f\uea40\uea41\uea42\uea43\uea44\uea45\uea46\uea47\uea48\uea49\uea4a\uea4b\uea4c\uea4d\uea4e\uea4f\uea50\uea51\uea52\uea53\uea54\uea55\uea56\uea57\uea58\uea59\uea5a\uea5b\uea5c\uea5d\uea5e\uea5f\uea60\ue
 a61\uea62\uea63\uea64\uea65\uea66\uea67\uea68\uea69\uea6a\uea6b\uea6c\uea6d\uea6e\uea6f\uea70\uea71\uea72\uea73\uea74\uea75\uea76\uea77\uea78\uea79\uea7a\uea7b\uea7c\uea7d\uea7e\uea7f\uea80\uea81\uea82\uea83\uea84\uea85\uea86\uea87\uea88\uea89\uea8a\uea8b\uea8c\uea8d\uea8e\uea8f\uea90\uea91\uea92\uea93\uea94\uea95\uea96\uea97\uea98\uea99\uea9a\uea9b\uea9c\uea9d\uea9e\uea9f\ueaa0\ueaa1\ueaa2\ueaa3\ueaa4\ueaa5\ueaa6\ueaa7\ueaa8\ueaa9\ueaaa\ueaab\ueaac\ueaad\ueaae\ueaaf\ueab0\ueab1\ueab2\ueab3\ueab4\ueab5\ueab6\ueab7\ueab8\ueab9\ueaba\ueabb\ueabc\ueabd\ueabe\ueabf\ueac0\ueac1\ueac2\ueac3\ueac4\ueac5\ueac6\ueac7\ueac8\ueac9\ueaca\ueacb\ueacc\ueacd\ueace\ueacf\uead0\uead1\uead2\uead3\uead4\uead5\uead6\uead7\uead8\uead9\ueada\ueadb\ueadc\ueadd\ueade\ueadf\ueae0\ueae1\ueae2\ueae3\ueae4\ueae5\ueae6\ueae7\ueae8\ueae9\ueaea\ueaeb\ueaec\ueaed\ueaee\ueaef\ueaf0\ueaf1\ueaf2\ueaf3\ueaf4\ueaf5\ueaf6\ueaf7\ueaf8\ueaf9\ueafa\ueafb\ueafc\ueafd\ueafe\ueaff\ueb00\ueb01\ueb02\ueb03\ueb04\ueb05\ueb06\ueb
 07\ueb08\ueb09\ueb0a\ueb0b\ueb0c\ueb0d\ueb0e\ueb0f\ueb10\ueb11\ueb12\ueb13\ueb14\ueb15\ueb16\ueb17\ueb18\ueb19\ueb1a\ueb1b\ueb1c\ueb1d\ueb1e\ueb1f\ueb20\ueb21\ueb22\ueb23\ueb24\ueb25\ueb26\ueb27\ueb28\ueb29\ueb2a\ueb2b\ueb2c\ueb2d\ueb2e\ueb2f\ueb30\ueb31\ueb32\ueb33\ueb34\ueb35\ueb36\ueb37\ueb38\ueb39\ueb3a\ueb3b\ueb3c\ueb3d\ueb3e\ueb3f\ueb40\ueb41\ueb42\ueb43\ueb44\ueb45\ueb46\ueb47\ueb48\ueb49\ueb4a\ueb4b\ueb4c\ueb4d\ueb4e\ueb4f\ueb50\ueb51\ueb52\ueb53\ueb54\ueb55\ueb56\ueb57\ueb58\ueb59\ueb5a\ueb5b\ueb5c\ueb5d\ueb5e\ueb5f\ueb60\ueb61\ueb62\ueb63\ueb64\ueb65\ueb66\ueb67\ueb68\ueb69\ueb6a\ueb6b\ueb6c\ueb6d\ueb6e\ueb6f\ueb70\ueb71\ueb72\ueb73\ueb74\ueb75\ueb76\ueb77\ueb78\ueb79\ueb7a\ueb7b\ueb7c\ueb7d\ueb7e\ueb7f\ueb80\ueb81\ueb82\ueb83\ueb84\ueb85\ueb86\ueb87\ueb88\ueb89\ueb8a\ueb8b\ueb8c\ueb8d\ueb8e\ueb8f\ueb90\ueb91\ueb92\ueb93\ueb94\ueb95\ueb96\ueb97\ueb98\ueb99\ueb9a\ueb9b\ueb9c\ueb9d\ueb9e\ueb9f\ueba0\ueba1\ueba2\ueba3\ueba4\ueba5\ueba6\ueba7\ueba8\ueba9\uebaa\uebab\uebac\ueba
 d\uebae\uebaf\uebb0\uebb1\uebb2\uebb3\uebb4\uebb5\uebb6\uebb7\uebb8\uebb9\uebba\uebbb\uebbc\uebbd\uebbe\uebbf\uebc0\uebc1\uebc2\uebc3\uebc4\uebc5\uebc6\uebc7\uebc8\uebc9\uebca\uebcb\uebcc\uebcd\uebce\uebcf\uebd0\uebd1\uebd2\uebd3\uebd4\uebd5\uebd6\uebd7\uebd8\uebd9\uebda\uebdb\uebdc\uebdd\uebde\uebdf\uebe0\uebe1\uebe2\uebe3\uebe4\uebe5\uebe6\uebe7\uebe8\uebe9\uebea\uebeb\uebec\uebed\uebee\uebef\uebf0\uebf1\uebf2\uebf3\uebf4\uebf5\uebf6\uebf7\uebf8\uebf9\uebfa\uebfb\uebfc\uebfd\uebfe\uebff\uec00\uec01\uec02\uec03\uec04\uec05\uec06\uec07\uec08\uec09\uec0a\uec0b\uec0c\uec0d\uec0e\uec0f\uec10\uec11\uec12\uec13\uec14\uec15\uec16\uec17\uec18\uec19\uec1a\uec1b\uec1c\uec1d\uec1e\uec1f\uec20\uec21\uec22\uec23\uec24\uec25\uec26\uec27\uec28\uec29\uec2a\uec2b\uec2c\uec2d\uec2e\uec2f\uec30\uec31\uec32\uec33\uec34\uec35\uec36\uec37\uec38\uec39\uec3a\uec3b\uec3c\uec3d\uec3e\uec3f\uec40\uec41\uec42\uec43\uec44\uec45\uec46\uec47\uec48\uec49\uec4a\uec4b\uec4c\uec4d\uec4e\uec4f\uec50\uec51\uec52\uec53
 \uec54\uec55\uec56\uec57\uec58\uec59\uec5a\uec5b\uec5c\uec5d\uec5e\uec5f\uec60\uec61\uec62\uec63\uec64\uec65\uec66\uec67\uec68\uec69\uec6a\uec6b\uec6c\uec6d\uec6e\uec6f\uec70\uec71\uec72\uec73\uec74\uec75\uec76\uec77\uec78\uec79\uec7a\uec7b\uec7c\uec7d\uec7e\uec7f\uec80\uec81\uec82\uec83\uec84\uec85\uec86\uec87\uec88\uec89\uec8a\uec8b\uec8c\uec8d\uec8e\uec8f\uec90\uec91\uec92\uec93\uec94\uec95\uec96\uec97\uec98\uec99\uec9a\uec9b\uec9c\uec9d\uec9e\uec9f\ueca0\ueca1\ueca2\ueca3\ueca4\ueca5\ueca6\ueca7\ueca8\ueca9\uecaa\uecab\uecac\uecad\uecae\uecaf\uecb0\uecb1\uecb2\uecb3\uecb4\uecb5\uecb6\uecb7\uecb8\uecb9\uecba\uecbb\uecbc\uecbd\uecbe\uecbf\uecc0\uecc1\uecc2\uecc3\uecc4\uecc5\uecc6\uecc7\uecc8\uecc9\uecca\ueccb\ueccc\ueccd\uecce\ueccf\uecd0\uecd1\uecd2\uecd3\uecd4\uecd5\uecd6\uecd7\uecd8\uecd9\uecda\uecdb\uecdc\uecdd\uecde\uecdf\uece0\uece1\uece2\uece3\uece4\uece5\uece6\uece7\uece8\uece9\uecea\ueceb\uecec\ueced\uecee\uecef\uecf0\uecf1\uecf2\uecf3\uecf4\uecf5\uecf6\uecf7\uecf8\uecf9\
 uecfa\uecfb\uecfc\uecfd\uecfe\uecff\ued00\ued01\ued02\ued03\ued04\ued05\ued06\ued07\ued08\ued09\ued0a\ued0b\ued0c\ued0d\ued0e\ued0f\ued10\ued11\ued12\ued13\ued14\ued15\ued16\ued17\ued18\ued19\ued1a\ued1b\ued1c\ued1d\ued1e\ued1f\ued20\ued21\ued22\ued23\ued24\ued25\ued26\ued27\ued28\ued29\ued2a\ued2b\ued2c\ued2d\ued2e\ued2f\ued30\ued31\ued32\ued33\ued34\ued35\ued36\ued37\ued38\ued39\ued3a\ued3b\ued3c\ued3d\ued3e\ued3f\ued40\ued41\ued42\ued43\ued44\ued45\ued46\ued47\ued48\ued49\ued4a\ued4b\ued4c\ued4d\ued4e\ued4f\ued50\ued51\ued52\ued53\ued54\ued55\ued56\ued57\ued58\ued59\ued5a\ued5b\ued5c\ued5d\ued5e\ued5f\ued60\ued61\ued62\ued63\ued64\ued65\ued66\ued67\ued68\ued69\ued6a\ued6b\ued6c\ued6d\ued6e\ued6f\ued70\ued71\ued72\ued73\ued74\ued75\ued76\ued77\ued78\ued79\ued7a\ued7b\ued7c\ued7d\ued7e\ued7f\ued80\ued81\ued82\ued83\ued84\ued85\ued86\ued87\ued88\ued89\ued8a\ued8b\ued8c\ued8d\ued8e\ued8f\ued90\ued91\ued92\ued93\ued94\ued95\ued96\ued97\ued98\ued99\ued9a\ued9b\ued9c\ued9d\ued9e\ued9f\u
 eda0\ueda1\ueda2\ueda3\ueda4\ueda5\ueda6\ueda7\ueda8\ueda9\uedaa\uedab\uedac\uedad\uedae\uedaf\uedb0\uedb1\uedb2\uedb3\uedb4\uedb5\uedb6\uedb7\uedb8\uedb9\uedba\uedbb\uedbc\uedbd\uedbe\uedbf\uedc0\uedc1\uedc2\uedc3\uedc4\uedc5\uedc6\uedc7\uedc8\uedc9\uedca\uedcb\uedcc\uedcd\uedce\uedcf\uedd0\uedd1\uedd2\uedd3\uedd4\uedd5\uedd6\uedd7\uedd8\uedd9\uedda\ueddb\ueddc\ueddd\uedde\ueddf\uede0\uede1\uede2\uede3\uede4\uede5\uede6\uede7\uede8\uede9\uedea\uedeb\uedec\ueded\uedee\uedef\uedf0\uedf1\uedf2\uedf3\uedf4\uedf5\uedf6\uedf7\uedf8\uedf9\uedfa\uedfb\uedfc\uedfd\uedfe\uedff\uee00\uee01\uee02\uee03\uee04\uee05\uee06\uee07\uee08\uee09\uee0a\uee0b\uee0c\uee0d\uee0e\uee0f\uee10\uee11\uee12\uee13\uee14\uee15\uee16\uee17\uee18\uee19\uee1a\uee1b\uee1c\uee1d\uee1e\uee1f\uee20\uee21\uee22\uee23\uee24\uee25\uee26\uee27\uee28\uee29\uee2a\uee2b\uee2c\uee2d\uee2e\uee2f\uee30\uee31\uee32\uee33\uee34\uee35\uee36\uee37\uee38\uee39\uee3a\uee3b\uee3c\uee3d\uee3e\uee3f\uee40\uee41\uee42\uee43\uee44\uee45\ue
 e46\uee47\uee48\uee49\uee4a\uee4b\uee4c\uee4d\uee4e\uee4f\uee50\uee51\uee52\uee53\uee54\uee55\uee56\uee57\uee58\uee59\uee5a\uee5b\uee5c\uee5d\uee5e\uee5f\uee60\uee61\uee62\uee63\uee64\uee65\uee66\uee67\uee68\uee69\uee6a\uee6b\uee6c\uee6d\uee6e\uee6f\uee70\uee71\uee72\uee73\uee74\uee75\uee76\uee77\uee78\uee79\uee7a\uee7b\uee7c\uee7d\uee7e\uee7f\uee80\uee81\uee82\uee83\uee84\uee85\uee86\uee87\uee88\uee89\uee8a\uee8b\uee8c\uee8d\uee8e\uee8f\uee90\uee91\uee92\uee93\uee94\uee95\uee96\uee97\uee98\uee99\uee9a\uee9b\uee9c\uee9d\uee9e\uee9f\ueea0\ueea1\ueea2\ueea3\ueea4\ueea5\ueea6\ueea7\ueea8\ueea9\ueeaa\ueeab\ueeac\ueead\ueeae\ueeaf\ueeb0\ueeb1\ueeb2\ueeb3\ueeb4\ueeb5\ueeb6\ueeb7\ueeb8\ueeb9\ueeba\ueebb\ueebc\ueebd\ueebe\ueebf\ueec0\ueec1\ueec2\ueec3\ueec4\ueec5\ueec6\ueec7\ueec8\ueec9\ueeca\ueecb\ueecc\ueecd\ueece\ueecf\ueed0\ueed1\ueed2\ueed3\ueed4\ueed5\ueed6\ueed7\ueed8\ueed9\ueeda\ueedb\ueedc\ueedd\ueede\ueedf\ueee0\ueee1\ueee2\ueee3\ueee4\ueee5\ueee6\ueee7\ueee8\ueee9\ueeea\ueeeb\uee
 ec\ueeed\ueeee\ueeef\ueef0\ueef1\ueef2\ueef3\ueef4\ueef5\ueef6\ueef7\ueef8\ueef9\ueefa\ueefb\ueefc\ueefd\ueefe\ueeff\uef00\uef01\uef02\uef03\uef04\uef05\uef06\uef07\uef08\uef09\uef0a\uef0b\uef0c\uef0d\uef0e\uef0f\uef10\uef11\uef12\uef13\uef14\uef15\uef16\uef17\uef18\uef19\uef1a\uef1b\uef1c\uef1d\uef1e\uef1f\uef20\uef21\uef22\uef23\uef24\uef25\uef26\uef27\uef28\uef29\uef2a\uef2b\uef2c\uef2d\uef2e\uef2f\uef30\uef31\uef32\uef33\uef34\uef35\uef36\uef37\uef38\uef39\uef3a\uef3b\uef3c\uef3d\uef3e\uef3f\uef40\uef41\uef42\uef43\uef44\uef45\uef46\uef47\uef48\uef49\uef4a\uef4b\uef4c\uef4d\uef4e\uef4f\uef50\uef51\uef52\uef53\uef54\uef55\uef56\uef57\uef58\uef59\uef5a\uef5b\uef5c\uef5d\uef5e\uef5f\uef60\uef61\uef62\uef63\uef64\uef65\uef66\uef67\uef68\uef69\uef6a\uef6b\uef6c\uef6d\uef6e\uef6f\uef70\uef71\uef72\uef73\uef74\uef75\uef76\uef77\uef78\uef79\uef7a\uef7b\uef7c\uef7d\uef7e\uef7f\uef80\uef81\uef82\uef83\uef84\uef85\uef86\uef87\uef88\uef89\uef8a\uef8b\uef8c\uef8d\uef8e\uef8f\uef90\uef91\uef9
 2\uef93\uef94\uef95\uef96\uef97\uef98\uef99\uef9a\uef9b\uef9c\uef9d\uef9e\uef9f\uefa0\uefa1\uefa2\uefa3\uefa4\uefa5\uefa6\uefa7\uefa8\uefa9\uefaa\uefab\uefac\uefad\uefae\uefaf\uefb0\uefb1\uefb2\uefb3\uefb4\uefb5\uefb6\uefb7\uefb8\uefb9\uefba\uefbb\uefbc\uefbd\uefbe\uefbf\uefc0\uefc1\uefc2\uefc3\uefc4\uefc5\uefc6\uefc7\uefc8\uefc9\uefca\uefcb\uefcc\uefcd\uefce\uefcf\uefd0\uefd1\uefd2\uefd3\uefd4\uefd5\uefd6\uefd7\uefd8\uefd9\uefda\uefdb\uefdc\uefdd\uefde\uefdf\uefe0\uefe1\uefe2\uefe3\uefe4\uefe5\uefe6\uefe7\uefe8\uefe9\uefea\uefeb\uefec\uefed\uefee\uefef\ueff0\ueff1\ueff2\ueff3\ueff4\ueff5\ueff6\ueff7\ueff8\ueff9\ueffa\ueffb\ueffc\ueffd\ueffe\uefff\uf000\uf001\uf002\uf003\uf004\uf005\uf006\uf007\uf008\uf009\uf00a\uf00b\uf00c\uf00d\uf00e\uf00f\uf010\uf011\uf012\uf013\uf014\uf015\uf016\uf017\uf018\uf019\uf01a\uf01b\uf01c\uf01d\uf01e\uf01f\uf020\uf021\uf022\uf023\uf024\uf025\uf026\uf027\uf028\uf029\uf02a\uf02b\uf02c\uf02d\uf02e\uf02f\uf030\uf031\uf032\uf033\uf034\uf035\uf036\uf037\uf038
 \uf039\uf03a\uf03b\uf03c\uf03d\uf03e\uf03f\uf040\uf041\uf042\uf043\uf044\uf045\uf046\uf047\uf048\uf049\uf04a\uf04b\uf04c\uf04d\uf04e\uf04f\uf050\uf051\uf052\uf053\uf054\uf055\uf056\uf057\uf058\uf059\uf05a\uf05b\uf05c\uf05d\uf05e\uf05f\uf060\uf061\uf062\uf063\uf064\uf065\uf066\uf067\uf068\uf069\uf06a\uf06b\uf06c\uf06d\uf06e\uf06f\uf070\uf071\uf072\uf073\uf074\uf075\uf076\uf077\uf078\uf079\uf07a\uf07b\uf07c\uf07d\uf07e\uf07f\uf080\uf081\uf082\uf083\uf084\uf085\uf086\uf087\uf088\uf089\uf08a\uf08b\uf08c\uf08d\uf08e\uf08f\uf090\uf091\uf092\uf093\uf094\uf095\uf096\uf097\uf098\uf099\uf09a\uf09b\uf09c\uf09d\uf09e\uf09f\uf0a0\uf0a1\uf0a2\uf0a3\uf0a4\uf0a5\uf0a6\uf0a7\uf0a8\uf0a9\uf0aa\uf0ab\uf0ac\uf0ad\uf0ae\uf0af\uf0b0\uf0b1\uf0b2\uf0b3\uf0b4\uf0b5\uf0b6\uf0b7\uf0b8\uf0b9\uf0ba\uf0bb\uf0bc\uf0bd\uf0be\uf0bf\uf0c0\uf0c1\uf0c2\uf0c3\uf0c4\uf0c5\uf0c6\uf0c7\uf0c8\uf0c9\uf0ca\uf0cb\uf0cc\uf0cd\uf0ce\uf0cf\uf0d0\uf0d1\uf0d2\uf0d3\uf0d4\uf0d5\uf0d6\uf0d7\uf0d8\uf0d9\uf0da\uf0db\uf0dc\uf0dd\uf0de\
 uf0df\uf0e0\uf0e1\uf0e2\uf0e3\uf0e4\uf0e5\uf0e6\uf0e7\uf0e8\uf0e9\uf0ea\uf0eb\uf0ec\uf0ed\uf0ee\uf0ef\uf0f0\uf0f1\uf0f2\uf0f3\uf0f4\uf0f5\uf0f6\uf0f7\uf0f8\uf0f9\uf0fa\uf0fb\uf0fc\uf0fd\uf0fe\uf0ff\uf100\uf101\uf102\uf103\uf104\uf105\uf106\uf107\uf108\uf109\uf10a\uf10b\uf10c\uf10d\uf10e\uf10f\uf110\uf111\uf112\uf113\uf114\uf115\uf116\uf117\uf118\uf119\uf11a\uf11b\uf11c\uf11d\uf11e\uf11f\uf120\uf121\uf122\uf123\uf124\uf125\uf126\uf127\uf128\uf129\uf12a\uf12b\uf12c\uf12d\uf12e\uf12f\uf130\uf131\uf132\uf133\uf134\uf135\uf136\uf137\uf138\uf139\uf13a\uf13b\uf13c\uf13d\uf13e\uf13f\uf140\uf141\uf142\uf143\uf144\uf145\uf146\uf147\uf148\uf149\uf14a\uf14b\uf14c\uf14d\uf14e\uf14f\uf150\uf151\uf152\uf153\uf154\uf155\uf156\uf157\uf158\uf159\uf15a\uf15b\uf15c\uf15d\uf15e\uf15f\uf160\uf161\uf162\uf163\uf164\uf165\uf166\uf167\uf168\uf169\uf16a\uf16b\uf16c\uf16d\uf16e\uf16f\uf170\uf171\uf172\uf173\uf174\uf175\uf176\uf177\uf178\uf179\uf17a\uf17b\uf17c\uf17d\uf17e\uf17f\uf180\uf181\uf182\uf183\uf184\u
 f185\uf186\uf187\uf188\uf189\uf18a\uf18b\uf18c\uf18d\uf18e\uf18f\uf190\uf191\uf192\uf193\uf194\uf195\uf196\uf197\uf198\uf199\uf19a\uf19b\uf19c\uf19d\uf19e\uf19f\uf1a0\uf1a1\uf1a2\uf1a3\uf1a4\uf1a5\uf1a6\uf1a7\uf1a8\uf1a9\uf1aa\uf1ab\uf1ac\uf1ad\uf1ae\uf1af\uf1b0\uf1b1\uf1b2\uf1b3\uf1b4\uf1b5\uf1b6\uf1b7\uf1b8\uf1b9\uf1ba\uf1bb\uf1bc\uf1bd\uf1be\uf1bf\uf1c0\uf1c1\uf1c2\uf1c3\uf1c4\uf1c5\uf1c6\uf1c7\uf1c8\uf1c9\uf1ca\uf1cb\uf1cc\uf1cd\uf1ce\uf1cf\uf1d0\uf1d1\uf1d2\uf1d3\uf1d4\uf1d5\uf1d6\uf1d7\uf1d8\uf1d9\uf1da\uf1db\uf1dc\uf1dd\uf1de\uf1df\uf1e0\uf1e1\uf1e2\uf1e3\uf1e4\uf1e5\uf1e6\uf1e7\uf1e8\uf1e9\uf1ea\uf1eb\uf1ec\uf1ed\uf1ee\uf1ef\uf1f0\uf1f1\uf1f2\uf1f3\uf1f4\uf1f5\uf1f6\uf1f7\uf1f8\uf1f9\uf1fa\uf1fb\uf1fc\uf1fd\uf1fe\uf1ff\uf200\uf201\uf202\uf203\uf204\uf205\uf206\uf207\uf208\uf209\uf20a\uf20b\uf20c\uf20d\uf20e\uf20f\uf210\uf211\uf212\uf213\uf214\uf215\uf216\uf217\uf218\uf219\uf21a\uf21b\uf21c\uf21d\uf21e\uf21f\uf220\uf221\uf222\uf223\uf224\uf225\uf226\uf227\uf228\uf229\uf22a\uf
 22b\uf22c\uf22d\uf22e\uf22f\uf230\uf231\uf232\uf233\uf234\uf235\uf236\uf237\uf238\uf239\uf23a\uf23b\uf23c\uf23d\uf23e\uf23f\uf240\uf241\uf242\uf243\uf244\uf245\uf246\uf247\uf248\uf249\uf24a\uf24b\uf24c\uf24d\uf24e\uf24f\uf250\uf251\uf252\uf253\uf254\uf255\uf256\uf257\uf258\uf259\uf25a\uf25b\uf25c\uf25d\uf25e\uf25f\uf260\uf261\uf262\uf263\uf264\uf265\uf266\uf267\uf268\uf269\uf26a\uf26b\uf26c\uf26d\uf26e\uf26f\uf270\uf271\uf272\uf273\uf274\uf275\uf276\uf277\uf278\uf279\uf27a\uf27b\uf27c\uf27d\uf27e\uf27f\uf280\uf281\uf282\uf283\uf284\uf285\uf286\uf287\uf288\uf289\uf28a\uf28b\uf28c\uf28d\uf28e\uf28f\uf290\uf291\uf292\uf293\uf294\uf295\uf296\uf297\uf298\uf299\uf29a\uf29b\uf29c\uf29d\uf29e\uf29f\uf2a0\uf2a1\uf2a2\uf2a3\uf2a4\uf2a5\uf2a6\uf2a7\uf2a8\uf2a9\uf2aa\uf2ab\uf2ac\uf2ad\uf2ae\uf2af\uf2b0\uf2b1\uf2b2\uf2b3\uf2b4\uf2b5\uf2b6\uf2b7\uf2b8\uf2b9\uf2ba\uf2bb\uf2bc\uf2bd\uf2be\uf2bf\uf2c0\uf2c1\uf2c2\uf2c3\uf2c4\uf2c5\uf2c6\uf2c7\uf2c8\uf2c9\uf2ca\uf2cb\uf2cc\uf2cd\uf2ce\uf2cf\uf2d0\uf2
 d1\uf2d2\uf2d3\uf2d4\uf2d5\uf2d6\uf2d7\uf2d8\uf2d9\uf2da\uf2db\uf2dc\uf2dd\uf2de\uf2df\uf2e0\uf2e1\uf2e2\uf2e3\uf2e4\uf2e5\uf2e6\uf2e7\uf2e8\uf2e9\uf2ea\uf2eb\uf2ec\uf2ed\uf2ee\uf2ef\uf2f0\uf2f1\uf2f2\uf2f3\uf2f4\uf2f5\uf2f6\uf2f7\uf2f8\uf2f9\uf2fa\uf2fb\uf2fc\uf2fd\uf2fe\uf2ff\uf300\uf301\uf302\uf303\uf304\uf305\uf306\uf307\uf308\uf309\uf30a\uf30b\uf30c\uf30d\uf30e\uf30f\uf310\uf311\uf312\uf313\uf314\uf315\uf316\uf317\uf318\uf319\uf31a\uf31b\uf31c\uf31d\uf31e\uf31f\uf320\uf321\uf322\uf323\uf324\uf325\uf326\uf327\uf328\uf329\uf32a\uf32b\uf32c\uf32d\uf32e\uf32f\uf330\uf331\uf332\uf333\uf334\uf335\uf336\uf337\uf338\uf339\uf33a\uf33b\uf33c\uf33d\uf33e\uf33f\uf340\uf341\uf342\uf343\uf344\uf345\uf346\uf347\uf348\uf349\uf34a\uf34b\uf34c\uf34d\uf34e\uf34f\uf350\uf351\uf352\uf353\uf354\uf355\uf356\uf357\uf358\uf359\uf35a\uf35b\uf35c\uf35d\uf35e\uf35f\uf360\uf361\uf362\uf363\uf364\uf365\uf366\uf367\uf368\uf369\uf36a\uf36b\uf36c\uf36d\uf36e\uf36f\uf370\uf371\uf372\uf373\uf374\uf375\uf376\uf37
 7\uf378\uf379\uf37a\uf37b\uf37c\uf37d\uf37e\uf37f\uf380\uf381\uf382\uf383\uf384\uf385\uf386\uf387\uf388\uf389\uf38a\uf38b\uf38c\uf38d\uf38e\uf38f\uf390\uf391\uf392\uf393\uf394\uf395\uf396\uf397\uf398\uf399\uf39a\uf39b\uf39c\uf39d\uf39e\uf39f\uf3a0\uf3a1\uf3a2\uf3a3\uf3a4\uf3a5\uf3a6\uf3a7\uf3a8\uf3a9\uf3aa\uf3ab\uf3ac\uf3ad\uf3ae\uf3af\uf3b0\uf3b1\uf3b2\uf3b3\uf3b4\uf3b5\uf3b6\uf3b7\uf3b8\uf3b9\uf3ba\uf3bb\uf3bc\uf3bd\uf3be\uf3bf\uf3c0\uf3c1\uf3c2\uf3c3\uf3c4\uf3c5\uf3c6\uf3c7\uf3c8\uf3c9\uf3ca\uf3cb\uf3cc\uf3cd\uf3ce\uf3cf\uf3d0\uf3d1\uf3d2\uf3d3\uf3d4\uf3d5\uf3d6\uf3d7\uf3d8\uf3d9\uf3da\uf3db\uf3dc\uf3dd\uf3de\uf3df\uf3e0\uf3e1\uf3e2\uf3e3\uf3e4\uf3e5\uf3e6\uf3e7\uf3e8\uf3e9\uf3ea\uf3eb\uf3ec\uf3ed\uf3ee\uf3ef\uf3f0\uf3f1\uf3f2\uf3f3\uf3f4\uf3f5\uf3f6\uf3f7\uf3f8\uf3f9\uf3fa\uf3fb\uf3fc\uf3fd\uf3fe\uf3ff\uf400\uf401\uf402\uf403\uf404\uf405\uf406\uf407\uf408\uf409\uf40a\uf40b\uf40c\uf40d\uf40e\uf40f\uf410\uf411\uf412\uf413\uf414\uf415\uf416\uf417\uf418\uf419\uf41a\uf41b\uf41c\uf41d
 \uf41e\uf41f\uf420\uf421\uf422\uf423\uf424\uf425\uf426\uf427\uf428\uf429\uf42a\uf42b\uf42c\uf42d\uf42e\uf42f\uf430\uf431\uf432\uf433\uf434\uf435\uf436\uf437\uf438\uf439\uf43a\uf43b\uf43c\uf43d\uf43e\uf43f\uf440\uf441\uf442\uf443\uf444\uf445\uf446\uf447\uf448\uf449\uf44a\uf44b\uf44c\uf44d\uf44e\uf44f\uf450\uf451\uf452\uf453\uf454\uf455\uf456\uf457\uf458\uf459\uf45a\uf45b\uf45c\uf45d\uf45e\uf45f\uf460\uf461\uf462\uf463\uf464\uf465\uf466\uf467\uf468\uf469\uf46a\uf46b\uf46c\uf46d\uf46e\uf46f\uf470\uf471\uf472\uf473\uf474\uf475\uf476\uf477\uf478\uf479\uf47a\uf47b\uf47c\uf47d\uf47e\uf47f\uf480\uf481\uf482\uf483\uf484\uf485\uf486\uf487\uf488\uf489\uf48a\uf48b\uf48c\uf48d\uf48e\uf48f\uf490\uf491\uf492\uf493\uf494\uf495\uf496\uf497\uf498\uf499\uf49a\uf49b\uf49c\uf49d\uf49e\uf49f\uf4a0\uf4a1\uf4a2\uf4a3\uf4a4\uf4a5\uf4a6\uf4a7\uf4a8\uf4a9\uf4aa\uf4ab\uf4ac\uf4ad\uf4ae\uf4af\uf4b0\uf4b1\uf4b2\uf4b3\uf4b4\uf4b5\uf4b6\uf4b7\uf4b8\uf4b9\uf4ba\uf4bb\uf4bc\uf4bd\uf4be\uf4bf\uf4c0\uf4c1\uf4c2\uf4c3\
 uf4c4\uf4c5\uf4c6\uf4c7\uf4c8\uf4c9\uf4ca\uf4cb\uf4cc\uf4cd\uf4ce\uf4cf\uf4d0\uf4d1\uf4d2\uf4d3\uf4d4\uf4d5\uf4d6\uf4d7\uf4d8\uf4d9\uf4da\uf4db\uf4dc\uf4dd\uf4de\uf4df\uf4e0\uf4e1\uf4e2\uf4e3\uf4e4\uf4e5\uf4e6\uf4e7\uf4e8\uf4e9\uf4ea\uf4eb\uf4ec\uf4ed\uf4ee\uf4ef\uf4f0\uf4f1\uf4f2\uf4f3\uf4f4\uf4f5\uf4f6\uf4f7\uf4f8\uf4f9\uf4fa\uf4fb\uf4fc\uf4fd\uf4fe\uf4ff\uf500\uf501\uf502\uf503\uf504\uf505\uf506\uf507\uf508\uf509\uf50a\uf50b\uf50c\uf50d\uf50e\uf50f\uf510\uf511\uf512\uf513\uf514\uf515\uf516\uf517\uf518\uf519\uf51a\uf51b\uf51c\uf51d\uf51e\uf51f\uf520\uf521\uf522\uf523\uf524\uf525\uf526\uf527\uf528\uf529\uf52a\uf52b\uf52c\uf52d\uf52e\uf52f\uf530\uf531\uf532\uf533\uf534\uf535\uf536\uf537\uf538\uf539\uf53a\uf53b\uf53c\uf53d\uf53e\uf53f\uf540\uf541\uf542\uf543\uf544\uf545\uf546\uf547\uf548\uf549\uf54a\uf54b\uf54c\uf54d\uf54e\uf54f\uf550\uf551\uf552\uf553\uf554\uf555\uf556\uf557\uf558\uf559\uf55a\uf55b\uf55c\uf55d\uf55e\uf55f\uf560\uf561\uf562\uf563\uf564\uf565\uf566\uf567\uf568\uf569\u
 f56a\uf56b\uf56c\uf56d\uf56e\uf56f\uf570\uf571\uf572\uf573\uf574\uf575\uf576\uf577\uf578\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf582\uf583\uf584\uf585\uf586\uf587\uf588\uf589\uf58a\uf58b\uf58c\uf58d\uf58e\uf58f\uf590\uf591\uf592\uf593\uf594\uf595\uf596\uf597\uf598\uf599\uf59a\uf59b\uf59c\uf59d\uf59e\uf59f\uf5a0\uf5a1\uf5a2\uf5a3\uf5a4\uf5a5\uf5a6\uf5a7\uf5a8\uf5a9\uf5aa\uf5ab\uf5ac\uf5ad\uf5ae\uf5af\uf5b0\uf5b1\uf5b2\uf5b3\uf5b4\uf5b5\uf5b6\uf5b7\uf5b8\uf5b9\uf5ba\uf5bb\uf5bc\uf5bd\uf5be\uf5bf\uf5c0\uf5c1\uf5c2\uf5c3\uf5c4\uf5c5\uf5c6\uf5c7\uf5c8\uf5c9\uf5ca\uf5cb\uf5cc\uf5cd\uf5ce\uf5cf\uf5d0\uf5d1\uf5d2\uf5d3\uf5d4\uf5d5\uf5d6\uf5d7\uf5d8\uf5d9\uf5da\uf5db\uf5dc\uf5dd\uf5de\uf5df\uf5e0\uf5e1\uf5e2\uf5e3\uf5e4\uf5e5\uf5e6\uf5e7\uf5e8\uf5e9\uf5ea\uf5eb\uf5ec\uf5ed\uf5ee\uf5ef\uf5f0\uf5f1\uf5f2\uf5f3\uf5f4\uf5f5\uf5f6\uf5f7\uf5f8\uf5f9\uf5fa\uf5fb\uf5fc\uf5fd\uf5fe\uf5ff\uf600\uf601\uf602\uf603\uf604\uf605\uf606\uf607\uf608\uf609\uf60a\uf60b\uf60c\uf60d\uf60e\uf60f\uf
 610\uf611\uf612\uf613\uf614\uf615\uf616\uf617\uf618\uf619\uf61a\uf61b\uf61c\uf61d\uf61e\uf61f\uf620\uf621\uf622\uf623\uf624\uf625\uf626\uf627\uf628\uf629\uf62a\uf62b\uf62c\uf62d\uf62e\uf62f\uf630\uf631\uf632\uf633\uf634\uf635\uf636\uf637\uf638\uf639\uf63a\uf63b\uf63c\uf63d\uf63e\uf63f\uf640\uf641\uf642\uf643\uf644\uf645\uf646\uf647\uf648\uf649\uf64a\uf64b\uf64c\uf64d\uf64e\uf64f\uf650\uf651\uf652\uf653\uf654\uf655\uf656\uf657\uf658\uf659\uf65a\uf65b\uf65c\uf65d\uf65e\uf65f\uf660\uf661\uf662\uf663\uf664\uf665\uf666\uf667\uf668\uf669\uf66a\uf66b\uf66c\uf66d\uf66e\uf66f\uf670\uf671\uf672\uf673\uf674\uf675\uf676\uf677\uf678\uf679\uf67a\uf67b\uf67c\uf67d\uf67e\uf67f\uf680\uf681\uf682\uf683\uf684\uf685\uf686\uf687\uf688\uf689\uf68a\uf68b\uf68c\uf68d\uf68e\uf68f\uf690\uf691\uf692\uf693\uf694\uf695\uf696\uf697\uf698\uf699\uf69a\uf69b\uf69c\uf69d\uf69e\uf69f\uf6a0\uf6a1\uf6a2\uf6a3\uf6a4\uf6a5\uf6a6\uf6a7\uf6a8\uf6a9\uf6aa\uf6ab\uf6ac\uf6ad\uf6ae\uf6af\uf6b0\uf6b1\uf6b2\uf6b3\uf6b4\uf6b5\uf6
 b6\uf6b7\uf6b8\uf6b9\uf6ba\uf6bb\uf6bc\uf6bd\uf6be\uf6bf\uf6c0\uf6c1\uf6c2\uf6c3\uf6c4\uf6c5\uf6c6\uf6c7\uf6c8\uf6c9\uf6ca\uf6cb\uf6cc\uf6cd\uf6ce\uf6cf\uf6d0\uf6d1\uf6d2\uf6d3\uf6d4\uf6d5\uf6d6\uf6d7\uf6d8\uf6d9\uf6da\uf6db\uf6dc\uf6dd\uf6de\uf6df\uf6e0\uf6e1\uf6e2\uf6e3\uf6e4\uf6e5\uf6e6\uf6e7\uf6e8\uf6e9\uf6ea\uf6eb\uf6ec\uf6ed\uf6ee\uf6ef\uf6f0\uf6f1\uf6f2\uf6f3\uf6f4\uf6f5\uf6f6\uf6f7\uf6f8\uf6f9\uf6fa\uf6fb\uf6fc\uf6fd\uf6fe\uf6ff\uf700\uf701\uf702\uf703\uf704\uf705\uf706\uf707\uf708\uf709\uf70a\uf70b\uf70c\uf70d\uf70e\uf70f\uf710\uf711\uf712\uf713\uf714\uf715\uf716\uf717\uf718\uf719\uf71a\uf71b\uf71c\uf71d\uf71e\uf71f\uf720\uf721\uf722\uf723\uf724\uf725\uf726\uf727\uf728\uf729\uf72a\uf72b\uf72c\uf72d\uf72e\uf72f\uf730\uf731\uf732\uf733\uf734\uf735\uf736\uf737\uf738\uf739\uf73a\uf73b\uf73c\uf73d\uf73e\uf73f\uf740\uf741\uf742\uf743\uf744\uf745\uf746\uf747\uf748\uf749\uf74a\uf74b\uf74c\uf74d\uf74e\uf74f\uf750\uf751\uf752\uf753\uf754\uf755\uf756\uf757\uf758\uf759\uf75a\uf75b\uf75
 c\uf75d\uf75e\uf75f\uf760\uf761\uf762\uf763\uf764\uf765\uf766\uf767\uf768\uf769\uf76a\uf76b\uf76c\uf76d\uf76e\uf76f\uf770\uf771\uf772\uf773\uf774\uf775\uf776\uf777\uf778\uf779\uf77a\uf77b\uf77c\uf77d\uf77e\uf77f\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff\uf800\uf801\uf802
 \uf803\uf804\uf805\uf806\uf807\uf808\uf809\uf80a\uf80b\uf80c\uf80d\uf80e\uf80f\uf810\uf811\uf812\uf813\uf814\uf815\uf816\uf817\uf818\uf819\uf81a\uf81b\uf81c\uf81d\uf81e\uf81f\uf820\uf821\uf822\uf823\uf824\uf825\uf826\uf827\uf828\uf829\uf82a\uf82b\uf82c\uf82d\uf82e\uf82f\uf830\uf831\uf832\uf833\uf834\uf835\uf836\uf837\uf838\uf839\uf83a\uf83b\uf83c\uf83d\uf83e\uf83f\uf840\uf841\uf842\uf843\uf844\uf845\uf846\uf847\uf848\uf849\uf84a\uf84b\uf84c\uf84d\uf84e\uf84f\uf850\uf851\uf852\uf853\uf854\uf855\uf856\uf857\uf858\uf859\uf85a\uf85b\uf85c\uf85d\uf85e\uf85f\uf860\uf861\uf862\uf863\uf864\uf865\uf866\uf867\uf868\uf869\uf86a\uf86b\uf86c\uf86d\uf86e\uf86f\uf870\uf871\uf872\uf873\uf874\uf875\uf876\uf877\uf878\uf879\uf87a\uf87b\uf87c\uf87d\uf87e\uf87f\uf880\uf881\uf882\uf883\uf884\uf885\uf886\uf887\uf888\uf889\uf88a\uf88b\uf88c\uf88d\uf88e\uf88f\uf890\uf891\uf892\uf893\uf894\uf895\uf896\uf897\uf898\uf899\uf89a\uf89b\uf89c\uf89d\uf89e\uf89f\uf8a0\uf8a1\uf8a2\uf8a3\uf8a4\uf8a5\uf8a6\uf8a7\uf8a8\
 uf8a9\uf8aa\uf8ab\uf8ac\uf8ad\uf8ae\uf8af\uf8b0\uf8b1\uf8b2\uf8b3\uf8b4\uf8b5\uf8b6\uf8b7\uf8b8\uf8b9\uf8ba\uf8bb\uf8bc\uf8bd\uf8be\uf8bf\uf8c0\uf8c1\uf8c2\uf8c3\uf8c4\uf8c5\uf8c6\uf8c7\uf8c8\uf8c9\uf8ca\uf8cb\uf8cc\uf8cd\uf8ce\uf8cf\uf8d0\uf8d1\uf8d2\uf8d3\uf8d4\uf8d5\uf8d6\uf8d7\uf8d8\uf8d9\uf8da\uf8db\uf8dc\uf8dd\uf8de\uf8df\uf8e0\uf8e1\uf8e2\uf8e3\uf8e4\uf8e5\uf8e6\uf8e7\uf8e8\uf8e9\uf8ea\uf8eb\uf8ec\uf8ed\uf8ee\uf8ef\uf8f0\uf8f1\uf8f2\uf8f3\uf8f4\uf8f5\uf8f6\uf8f7\uf8f8\uf8f9\uf8fa\uf8fb\uf8fc\uf8fd\uf8fe\uf8ff'
-
-try:
-    Cs = eval(r"'\ud800\ud801\ud802\ud803\ud804\ud805\ud806\ud807\ud808\ud809\ud80a\ud80b\ud80c\ud80d\ud80e\ud80f\ud810\ud811\ud812\ud813\ud814\ud815\ud816\ud817\ud818\ud819\ud81a\ud81b\ud81c\ud81d\ud81e\ud81f\ud820\ud821\ud822\ud823\ud824\ud825\ud826\ud827\ud828\ud829\ud82a\ud82b\ud82c\ud82d\ud82e\ud82f\ud830\ud831\ud832\ud833\ud834\ud835\ud836\ud837\ud838\ud839\ud83a\ud83b\ud83c\ud83d\ud83e\ud83f\ud840\ud841\ud842\ud843\ud844\ud845\ud846\ud847\ud848\ud849\ud84a\ud84b\ud84c\ud84d\ud84e\ud84f\ud850\ud851\ud852\ud853\ud854\ud855\ud856\ud857\ud858\ud859\ud85a\ud85b\ud85c\ud85d\ud85e\ud85f\ud860\ud861\ud862\ud863\ud864\ud865\ud866\ud867\ud868\ud869\ud86a\ud86b\ud86c\ud86d\ud86e\ud86f\ud870\ud871\ud872\ud873\ud874\ud875\ud876\ud877\ud878\ud879\ud87a\ud87b\ud87c\ud87d\ud87e\ud87f\ud880\ud881\ud882\ud883\ud884\ud885\ud886\ud887\ud888\ud889\ud88a\ud88b\ud88c\ud88d\ud88e\ud88f\ud890\ud891\ud892\ud893\ud894\ud895\ud896\ud897\ud898\ud899\ud89a\ud89b\ud89c\ud89d\ud89e\ud89f\ud8a0\ud8a1\ud8a2\u
 d8a3\ud8a4\ud8a5\ud8a6\ud8a7\ud8a8\ud8a9\ud8aa\ud8ab\ud8ac\ud8ad\ud8ae\ud8af\ud8b0\ud8b1\ud8b2\ud8b3\ud8b4\ud8b5\ud8b6\ud8b7\ud8b8\ud8b9\ud8ba\ud8bb\ud8bc\ud8bd\ud8be\ud8bf\ud8c0\ud8c1\ud8c2\ud8c3\ud8c4\ud8c5\ud8c6\ud8c7\ud8c8\ud8c9\ud8ca\ud8cb\ud8cc\ud8cd\ud8ce\ud8cf\ud8d0\ud8d1\ud8d2\ud8d3\ud8d4\ud8d5\ud8d6\ud8d7\ud8d8\ud8d9\ud8da\ud8db\ud8dc\ud8dd\ud8de\ud8df\ud8e0\ud8e1\ud8e2\ud8e3\ud8e4\ud8e5\ud8e6\ud8e7\ud8e8\ud8e9\ud8ea\ud8eb\ud8ec\ud8ed\ud8ee\ud8ef\ud8f0\ud8f1\ud8f2\ud8f3\ud8f4\ud8f5\ud8f6\ud8f7\ud8f8\ud8f9\ud8fa\ud8fb\ud8fc\ud8fd\ud8fe\ud8ff\ud900\ud901\ud902\ud903\ud904\ud905\ud906\ud907\ud908\ud909\ud90a\ud90b\ud90c\ud90d\ud90e\ud90f\ud910\ud911\ud912\ud913\ud914\ud915\ud916\ud917\ud918\ud919\ud91a\ud91b\ud91c\ud91d\ud91e\ud91f\ud920\ud921\ud922\ud923\ud924\ud925\ud926\ud927\ud928\ud929\ud92a\ud92b\ud92c\ud92d\ud92e\ud92f\ud930\ud931\ud932\ud933\ud934\ud935\ud936\ud937\ud938\ud939\ud93a\ud93b\ud93c\ud93d\ud93e\ud93f\ud940\ud941\ud942\ud943\ud944\ud945\ud946\ud947\ud948\ud
 949\ud94a\ud94b\ud94c\ud94d\ud94e\ud94f\ud950\ud951\ud952\ud953\ud954\ud955\ud956\ud957\ud958\ud959\ud95a\ud95b\ud95c\ud95d\ud95e\ud95f\ud960\ud961\ud962\ud963\ud964\ud965\ud966\ud967\ud968\ud969\ud96a\ud96b\ud96c\ud96d\ud96e\ud96f\ud970\ud971\ud972\ud973\ud974\ud975\ud976\ud977\ud978\ud979\ud97a\ud97b\ud97c\ud97d\ud97e\ud97f\ud980\ud981\ud982\ud983\ud984\ud985\ud986\ud987\ud988\ud989\ud98a\ud98b\ud98c\ud98d\ud98e\ud98f\ud990\ud991\ud992\ud993\ud994\ud995\ud996\ud997\ud998\ud999\ud99a\ud99b\ud99c\ud99d\ud99e\ud99f\ud9a0\ud9a1\ud9a2\ud9a3\ud9a4\ud9a5\ud9a6\ud9a7\ud9a8\ud9a9\ud9aa\ud9ab\ud9ac\ud9ad\ud9ae\ud9af\ud9b0\ud9b1\ud9b2\ud9b3\ud9b4\ud9b5\ud9b6\ud9b7\ud9b8\ud9b9\ud9ba\ud9bb\ud9bc\ud9bd\ud9be\ud9bf\ud9c0\ud9c1\ud9c2\ud9c3\ud9c4\ud9c5\ud9c6\ud9c7\ud9c8\ud9c9\ud9ca\ud9cb\ud9cc\ud9cd\ud9ce\ud9cf\ud9d0\ud9d1\ud9d2\ud9d3\ud9d4\ud9d5\ud9d6\ud9d7\ud9d8\ud9d9\ud9da\ud9db\ud9dc\ud9dd\ud9de\ud9df\ud9e0\ud9e1\ud9e2\ud9e3\ud9e4\ud9e5\ud9e6\ud9e7\ud9e8\ud9e9\ud9ea\ud9eb\ud9ec\ud9ed\ud9ee\ud9
 ef\ud9f0\ud9f1\ud9f2\ud9f3\ud9f4\ud9f5\ud9f6\ud9f7\ud9f8\ud9f9\ud9fa\ud9fb\ud9fc\ud9fd\ud9fe\ud9ff\uda00\uda01\uda02\uda03\uda04\uda05\uda06\uda07\uda08\uda09\uda0a\uda0b\uda0c\uda0d\uda0e\uda0f\uda10\uda11\uda12\uda13\uda14\uda15\uda16\uda17\uda18\uda19\uda1a\uda1b\uda1c\uda1d\uda1e\uda1f\uda20\uda21\uda22\uda23\uda24\uda25\uda26\uda27\uda28\uda29\uda2a\uda2b\uda2c\uda2d\uda2e\uda2f\uda30\uda31\uda32\uda33\uda34\uda35\uda36\uda37\uda38\uda39\uda3a\uda3b\uda3c\uda3d\uda3e\uda3f\uda40\uda41\uda42\uda43\uda44\uda45\uda46\uda47\uda48\uda49\uda4a\uda4b\uda4c\uda4d\uda4e\uda4f\uda50\uda51\uda52\uda53\uda54\uda55\uda56\uda57\uda58\uda59\uda5a\uda5b\uda5c\uda5d\uda5e\uda5f\uda60\uda61\uda62\uda63\uda64\uda65\uda66\uda67\uda68\uda69\uda6a\uda6b\uda6c\uda6d\uda6e\uda6f\uda70\uda71\uda72\uda73\uda74\uda75\uda76\uda77\uda78\uda79\uda7a\uda7b\uda7c\uda7d\uda7e\uda7f\uda80\uda81\uda82\uda83\uda84\uda85\uda86\uda87\uda88\uda89\uda8a\uda8b\uda8c\uda8d\uda8e\uda8f\uda90\uda91\uda92\uda93\uda94\uda9
 5\uda96\uda97\uda98\uda99\uda9a\uda9b\uda9c\uda9d\uda9e\uda9f\udaa0\udaa1\udaa2\udaa3\udaa4\udaa5\udaa6\udaa7\udaa8\udaa9\udaaa\udaab\udaac\udaad\udaae\udaaf\udab0\udab1\udab2\udab3\udab4\udab5\udab6\udab7\udab8\udab9\udaba\udabb\udabc\udabd\udabe\udabf\udac0\udac1\udac2\udac3\udac4\udac5\udac6\udac7\udac8\udac9\udaca\udacb\udacc\udacd\udace\udacf\udad0\udad1\udad2\udad3\udad4\udad5\udad6\udad7\udad8\udad9\udada\udadb\udadc\udadd\udade\udadf\udae0\udae1\udae2\udae3\udae4\udae5\udae6\udae7\udae8\udae9\udaea\udaeb\udaec\udaed\udaee\udaef\udaf0\udaf1\udaf2\udaf3\udaf4\udaf5\udaf6\udaf7\udaf8\udaf9\udafa\udafb\udafc\udafd\udafe\udaff\udb00\udb01\udb02\udb03\udb04\udb05\udb06\udb07\udb08\udb09\udb0a\udb0b\udb0c\udb0d\udb0e\udb0f\udb10\udb11\udb12\udb13\udb14\udb15\udb16\udb17\udb18\udb19\udb1a\udb1b\udb1c\udb1d\udb1e\udb1f\udb20\udb21\udb22\udb23\udb24\udb25\udb26\udb27\udb28\udb29\udb2a\udb2b\udb2c\udb2d\udb2e\udb2f\udb30\udb31\udb32\udb33\udb34\udb35\udb36\udb37\udb38\udb39\udb3a\udb3b
 \udb3c\udb3d\udb3e\udb3f\udb40\udb41\udb42\udb43\udb44\udb45\udb46\udb47\udb48\udb49\udb4a\udb4b\udb4c\udb4d\udb4e\udb4f\udb50\udb51\udb52\udb53\udb54\udb55\udb56\udb57\udb58\udb59\udb5a\udb5b\udb5c\udb5d\udb5e\udb5f\udb60\udb61\udb62\udb63\udb64\udb65\udb66\udb67\udb68\udb69\udb6a\udb6b\udb6c\udb6d\udb6e\udb6f\udb70\udb71\udb72\udb73\udb74\udb75\udb76\udb77\udb78\udb79\udb7a\udb7b\udb7c\udb7d\udb7e\udb7f\udb80\udb81\udb82\udb83\udb84\udb85\udb86\udb87\udb88\udb89\udb8a\udb8b\udb8c\udb8d\udb8e\udb8f\udb90\udb91\udb92\udb93\udb94\udb95\udb96\udb97\udb98\udb99\udb9a\udb9b\udb9c\udb9d\udb9e\udb9f\udba0\udba1\udba2\udba3\udba4\udba5\udba6\udba7\udba8\udba9\udbaa\udbab\udbac\udbad\udbae\udbaf\udbb0\udbb1\udbb2\udbb3\udbb4\udbb5\udbb6\udbb7\udbb8\udbb9\udbba\udbbb\udbbc\udbbd\udbbe\udbbf\udbc0\udbc1\udbc2\udbc3\udbc4\udbc5\udbc6\udbc7\udbc8\udbc9\udbca\udbcb\udbcc\udbcd\udbce\udbcf\udbd0\udbd1\udbd2\udbd3\udbd4\udbd5\udbd6\udbd7\udbd8\udbd9\udbda\udbdb\udbdc\udbdd\udbde\udbdf\udbe0\udbe1\
 udbe2\udbe3\udbe4\udbe5\udbe6\udbe7\udbe8\udbe9\udbea\udbeb\udbec\udbed\udbee\udbef\udbf0\udbf1\udbf2\udbf3\udbf4\udbf5\udbf6\udbf7\udbf8\udbf9\udbfa\udbfb\udbfc\udbfd\udbfe\U0010fc00\udc01\udc02\udc03\udc04\udc05\udc06\udc07\udc08\udc09\udc0a\udc0b\udc0c\udc0d\udc0e\udc0f\udc10\udc11\udc12\udc13\udc14\udc15\udc16\udc17\udc18\udc19\udc1a\udc1b\udc1c\udc1d\udc1e\udc1f\udc20\udc21\udc22\udc23\udc24\udc25\udc26\udc27\udc28\udc29\udc2a\udc2b\udc2c\udc2d\udc2e\udc2f\udc30\udc31\udc32\udc33\udc34\udc35\udc36\udc37\udc38\udc39\udc3a\udc3b\udc3c\udc3d\udc3e\udc3f\udc40\udc41\udc42\udc43\udc44\udc45\udc46\udc47\udc48\udc49\udc4a\udc4b\udc4c\udc4d\udc4e\udc4f\udc50\udc51\udc52\udc53\udc54\udc55\udc56\udc57\udc58\udc59\udc5a\udc5b\udc5c\udc5d\udc5e\udc5f\udc60\udc61\udc62\udc63\udc64\udc65\udc66\udc67\udc68\udc69\udc6a\udc6b\udc6c\udc6d\udc6e\udc6f\udc70\udc71\udc72\udc73\udc74\udc75\udc76\udc77\udc78\udc79\udc7a\udc7b\udc7c\udc7d\udc7e\udc7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc
 88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff\udd00\udd01\udd02\udd03\udd04\udd05\udd06\udd07\udd08\udd09\udd0a\udd0b\udd0c\udd0d\udd0e\udd0f\udd10\udd11\udd12\udd13\udd14\udd15\udd16\udd17\udd18\udd19\udd1a\udd1b\udd1c\udd1d\udd1e\udd1f\udd20\udd21\udd22\udd23\udd24\udd25\udd26\udd27\udd28\udd29\udd2a\udd2b\udd2c\udd2d\udd2
 e\udd2f\udd30\udd31\udd32\udd33\udd34\udd35\udd36\udd37\udd38\udd39\udd3a\udd3b\udd3c\udd3d\udd3e\udd3f\udd40\udd41\udd42\udd43\udd44\udd45\udd46\udd47\udd48\udd49\udd4a\udd4b\udd4c\udd4d\udd4e\udd4f\udd50\udd51\udd52\udd53\udd54\udd55\udd56\udd57\udd58\udd59\udd5a\udd5b\udd5c\udd5d\udd5e\udd5f\udd60\udd61\udd62\udd63\udd64\udd65\udd66\udd67\udd68\udd69\udd6a\udd6b\udd6c\udd6d\udd6e\udd6f\udd70\udd71\udd72\udd73\udd74\udd75\udd76\udd77\udd78\udd79\udd7a\udd7b\udd7c\udd7d\udd7e\udd7f\udd80\udd81\udd82\udd83\udd84\udd85\udd86\udd87\udd88\udd89\udd8a\udd8b\udd8c\udd8d\udd8e\udd8f\udd90\udd91\udd92\udd93\udd94\udd95\udd96\udd97\udd98\udd99\udd9a\udd9b\udd9c\udd9d\udd9e\udd9f\udda0\udda1\udda2\udda3\udda4\udda5\udda6\udda7\udda8\udda9\uddaa\uddab\uddac\uddad\uddae\uddaf\uddb0\uddb1\uddb2\uddb3\uddb4\uddb5\uddb6\uddb7\uddb8\uddb9\uddba\uddbb\uddbc\uddbd\uddbe\uddbf\uddc0\uddc1\uddc2\uddc3\uddc4\uddc5\uddc6\uddc7\uddc8\uddc9\uddca\uddcb\uddcc\uddcd\uddce\uddcf\uddd0\uddd1\uddd2\uddd3\uddd4
 \uddd5\uddd6\uddd7\uddd8\uddd9\uddda\udddb\udddc\udddd\uddde\udddf\udde0\udde1\udde2\udde3\udde4\udde5\udde6\udde7\udde8\udde9\uddea\uddeb\uddec\udded\uddee\uddef\uddf0\uddf1\uddf2\uddf3\uddf4\uddf5\uddf6\uddf7\uddf8\uddf9\uddfa\uddfb\uddfc\uddfd\uddfe\uddff\ude00\ude01\ude02\ude03\ude04\ude05\ude06\ude07\ude08\ude09\ude0a\ude0b\ude0c\ude0d\ude0e\ude0f\ude10\ude11\ude12\ude13\ude14\ude15\ude16\ude17\ude18\ude19\ude1a\ude1b\ude1c\ude1d\ude1e\ude1f\ude20\ude21\ude22\ude23\ude24\ude25\ude26\ude27\ude28\ude29\ude2a\ude2b\ude2c\ude2d\ude2e\ude2f\ude30\ude31\ude32\ude33\ude34\ude35\ude36\ude37\ude38\ude39\ude3a\ude3b\ude3c\ude3d\ude3e\ude3f\ude40\ude41\ude42\ude43\ude44\ude45\ude46\ude47\ude48\ude49\ude4a\ude4b\ude4c\ude4d\ude4e\ude4f\ude50\ude51\ude52\ude53\ude54\ude55\ude56\ude57\ude58\ude59\ude5a\ude5b\ude5c\ude5d\ude5e\ude5f\ude60\ude61\ude62\ude63\ude64\ude65\ude66\ude67\ude68\ude69\ude6a\ude6b\ude6c\ude6d\ude6e\ude6f\ude70\ude71\ude72\ude73\ude74\ude75\ude76\ude77\ude78\ude79\ude7a\
 ude7b\ude7c\ude7d\ude7e\ude7f\ude80\ude81\ude82\ude83\ude84\ude85\ude86\ude87\ude88\ude89\ude8a\ude8b\ude8c\ude8d\ude8e\ude8f\ude90\ude91\ude92\ude93\ude94\ude95\ude96\ude97\ude98\ude99\ude9a\ude9b\ude9c\ude9d\ude9e\ude9f\udea0\udea1\udea2\udea3\udea4\udea5\udea6\udea7\udea8\udea9\udeaa\udeab\udeac\udead\udeae\udeaf\udeb0\udeb1\udeb2\udeb3\udeb4\udeb5\udeb6\udeb7\udeb8\udeb9\udeba\udebb\udebc\udebd\udebe\udebf\udec0\udec1\udec2\udec3\udec4\udec5\udec6\udec7\udec8\udec9\udeca\udecb\udecc\udecd\udece\udecf\uded0\uded1\uded2\uded3\uded4\uded5\uded6\uded7\uded8\uded9\udeda\udedb\udedc\udedd\udede\udedf\udee0\udee1\udee2\udee3\udee4\udee5\udee6\udee7\udee8\udee9\udeea\udeeb\udeec\udeed\udeee\udeef\udef0\udef1\udef2\udef3\udef4\udef5\udef6\udef7\udef8\udef9\udefa\udefb\udefc\udefd\udefe\udeff\udf00\udf01\udf02\udf03\udf04\udf05\udf06\udf07\udf08\udf09\udf0a\udf0b\udf0c\udf0d\udf0e\udf0f\udf10\udf11\udf12\udf13\udf14\udf15\udf16\udf17\udf18\udf19\udf1a\udf1b\udf1c\udf1d\udf1e\udf1f\udf20\u
 df21\udf22\udf23\udf24\udf25\udf26\udf27\udf28\udf29\udf2a\udf2b\udf2c\udf2d\udf2e\udf2f\udf30\udf31\udf32\udf33\udf34\udf35\udf36\udf37\udf38\udf39\udf3a\udf3b\udf3c\udf3d\udf3e\udf3f\udf40\udf41\udf42\udf43\udf44\udf45\udf46\udf47\udf48\udf49\udf4a\udf4b\udf4c\udf4d\udf4e\udf4f\udf50\udf51\udf52\udf53\udf54\udf55\udf56\udf57\udf58\udf59\udf5a\udf5b\udf5c\udf5d\udf5e\udf5f\udf60\udf61\udf62\udf63\udf64\udf65\udf66\udf67\udf68\udf69\udf6a\udf6b\udf6c\udf6d\udf6e\udf6f\udf70\udf71\udf72\udf73\udf74\udf75\udf76\udf77\udf78\udf79\udf7a\udf7b\udf7c\udf7d\udf7e\udf7f\udf80\udf81\udf82\udf83\udf84\udf85\udf86\udf87\udf88\udf89\udf8a\udf8b\udf8c\udf8d\udf8e\udf8f\udf90\udf91\udf92\udf93\udf94\udf95\udf96\udf97\udf98\udf99\udf9a\udf9b\udf9c\udf9d\udf9e\udf9f\udfa0\udfa1\udfa2\udfa3\udfa4\udfa5\udfa6\udfa7\udfa8\udfa9\udfaa\udfab\udfac\udfad\udfae\udfaf\udfb0\udfb1\udfb2\udfb3\udfb4\udfb5\udfb6\udfb7\udfb8\udfb9\udfba\udfbb\udfbc\udfbd\udfbe\udfbf\udfc0\udfc1\udfc2\udfc3\udfc4\udfc5\udfc6\ud
 fc7\udfc8\udfc9\udfca\udfcb\udfcc\udfcd\udfce\udfcf\udfd0\udfd1\udfd2\udfd3\udfd4\udfd5\udfd6\udfd7\udfd8\udfd9\udfda\udfdb\udfdc\udfdd\udfde\udfdf\udfe0\udfe1\udfe2\udfe3\udfe4\udfe5\udfe6\udfe7\udfe8\udfe9\udfea\udfeb\udfec\udfed\udfee\udfef\udff0\udff1\udff2\udff3\udff4\udff5\udff6\udff7\udff8\udff9\udffa\udffb\udffc\udffd\udffe\udfff'")
-except UnicodeDecodeError:
-    Cs = '' # Jython can't handle isolated surrogates
-
-Ll = u'abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u
 0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u0234\u0235\u0236\u0237\u0238\u0239\u023c\u023f\u0240\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d\u028e\u028f\u0290\u0291\u0292\u0293\u0294\u0295\u0296\u0297\u0298\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac\u02ad\u02ae\u02af\u0390\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u0
 3ef\u03f0\u03f1\u03f2\u03f3\u03f5\u03f8\u03fb\u03fc\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0561\u0562\u0563\u0564\u0565\u0566\u0567\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b\u057c\u057d\u05
 7e\u057f\u0580\u0581\u0582\u0583\u0584\u0585\u0586\u0587\u1d00\u1d01\u1d02\u1d03\u1d04\u1d05\u1d06\u1d07\u1d08\u1d09\u1d0a\u1d0b\u1d0c\u1d0d\u1d0e\u1d0f\u1d10\u1d11\u1d12\u1d13\u1d14\u1d15\u1d16\u1d17\u1d18\u1d19\u1d1a\u1d1b\u1d1c\u1d1d\u1d1e\u1d1f\u1d20\u1d21\u1d22\u1d23\u1d24\u1d25\u1d26\u1d27\u1d28\u1d29\u1d2a\u1d2b\u1d62\u1d63\u1d64\u1d65\u1d66\u1d67\u1d68\u1d69\u1d6a\u1d6b\u1d6c\u1d6d\u1d6e\u1d6f\u1d70\u1d71\u1d72\u1d73\u1d74\u1d75\u1d76\u1d77\u1d79\u1d7a\u1d7b\u1d7c\u1d7d\u1d7e\u1d7f\u1d80\u1d81\u1d82\u1d83\u1d84\u1d85\u1d86\u1d87\u1d88\u1d89\u1d8a\u1d8b\u1d8c\u1d8d\u1d8e\u1d8f\u1d90\u1d91\u1d92\u1d93\u1d94\u1d95\u1d96\u1d97\u1d98\u1d99\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e7
 1\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98\u1e99\u1e9a\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6\u1fb7
 \u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1

<TRUNCATED>

[09/59] [abbrv] Revert "AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)"

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/templates.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/templates.rst b/ambari-common/src/main/python/jinja2/docs/templates.rst
new file mode 100644
index 0000000..4a1f6ff
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/templates.rst
@@ -0,0 +1,1365 @@
+Template Designer Documentation
+===============================
+
+.. highlight:: html+jinja
+
+This document describes the syntax and semantics of the template engine and
+will be most useful as reference to those creating Jinja templates.  As the
+template engine is very flexible the configuration from the application might
+be slightly different from here in terms of delimiters and behavior of
+undefined values.
+
+
+Synopsis
+--------
+
+A template is simply a text file.  It can generate any text-based format
+(HTML, XML, CSV, LaTeX, etc.).  It doesn't have a specific extension,
+``.html`` or ``.xml`` are just fine.
+
+A template contains **variables** or **expressions**, which get replaced with
+values when the template is evaluated, and tags, which control the logic of
+the template.  The template syntax is heavily inspired by Django and Python.
+
+Below is a minimal template that illustrates a few basics.  We will cover
+the details later in that document::
+
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+    <html lang="en">
+    <head>
+        <title>My Webpage</title>
+    </head>
+    <body>
+        <ul id="navigation">
+        {% for item in navigation %}
+            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
+        {% endfor %}
+        </ul>
+
+        <h1>My Webpage</h1>
+        {{ a_variable }}
+    </body>
+    </html>
+
+This covers the default settings.  The application developer might have
+changed the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar.
+
+There are two kinds of delimiers. ``{% ... %}`` and ``{{ ... }}``.  The first
+one is used to execute statements such as for-loops or assign values, the
+latter prints the result of the expression to the template.
+
+.. _variables:
+
+Variables
+---------
+
+The application passes variables to the templates you can mess around in the
+template.  Variables may have attributes or elements on them you can access
+too.  How a variable looks like, heavily depends on the application providing
+those.
+
+You can use a dot (``.``) to access attributes of a variable, alternative the
+so-called "subscript" syntax (``[]``) can be used.  The following lines do
+the same::
+
+    {{ foo.bar }}
+    {{ foo['bar'] }}
+
+It's important to know that the curly braces are *not* part of the variable
+but the print statement.  If you access variables inside tags don't put the
+braces around.
+
+If a variable or attribute does not exist you will get back an undefined
+value.  What you can do with that kind of value depends on the application
+configuration, the default behavior is that it evaluates to an empty string
+if printed and that you can iterate over it, but every other operation fails.
+
+.. _notes-on-subscriptions:
+
+.. admonition:: Implementation
+
+    For convenience sake ``foo.bar`` in Jinja2 does the following things on
+    the Python layer:
+
+    -   check if there is an attribute called `bar` on `foo`.
+    -   if there is not, check if there is an item ``'bar'`` in `foo`.
+    -   if there is not, return an undefined object.
+
+    ``foo['bar']`` on the other hand works mostly the same with the a small
+    difference in the order:
+
+    -   check if there is an item ``'bar'`` in `foo`.
+    -   if there is not, check if there is an attribute called `bar` on `foo`.
+    -   if there is not, return an undefined object.
+
+    This is important if an object has an item or attribute with the same
+    name.  Additionally there is the :func:`attr` filter that just looks up
+    attributes.
+
+.. _filters:
+
+Filters
+-------
+
+Variables can by modified by **filters**.  Filters are separated from the
+variable by a pipe symbol (``|``) and may have optional arguments in
+parentheses.  Multiple filters can be chained.  The output of one filter is
+applied to the next.
+
+``{{ name|striptags|title }}`` for example will remove all HTML Tags from the
+`name` and title-cases it.  Filters that accept arguments have parentheses
+around the arguments, like a function call.  This example will join a list
+by commas:  ``{{ list|join(', ') }}``.
+
+The :ref:`builtin-filters` below describes all the builtin filters.
+
+.. _tests:
+
+Tests
+-----
+
+Beside filters there are also so called "tests" available.  Tests can be used
+to test a variable against a common expression.  To test a variable or
+expression you add `is` plus the name of the test after the variable.  For
+example to find out if a variable is defined you can do ``name is defined``
+which will then return true or false depending on if `name` is defined.
+
+Tests can accept arguments too.  If the test only takes one argument you can
+leave out the parentheses to group them.  For example the following two
+expressions do the same::
+
+    {% if loop.index is divisibleby 3 %}
+    {% if loop.index is divisibleby(3) %}
+
+The :ref:`builtin-tests` below describes all the builtin tests.
+
+
+Comments
+--------
+
+To comment-out part of a line in a template, use the comment syntax which is
+by default set to ``{# ... #}``.  This is useful to comment out parts of the
+template for debugging or to add information for other template designers or
+yourself::
+
+    {# note: disabled template because we no longer use this
+        {% for user in users %}
+            ...
+        {% endfor %}
+    #}
+
+
+Whitespace Control
+------------------
+
+In the default configuration whitespace is not further modified by the
+template engine, so each whitespace (spaces, tabs, newlines etc.) is returned
+unchanged.  If the application configures Jinja to `trim_blocks` the first
+newline after a a template tag is removed automatically (like in PHP).
+
+But you can also strip whitespace in templates by hand.  If you put an minus
+sign (``-``) to the start or end of an block (for example a for tag), a
+comment or variable expression you can remove the whitespaces after or before
+that block::
+
+    {% for item in seq -%}
+        {{ item }}
+    {%- endfor %}
+    
+This will yield all elements without whitespace between them.  If `seq` was
+a list of numbers from ``1`` to ``9`` the output would be ``123456789``.
+
+If :ref:`line-statements` are enabled they strip leading whitespace
+automatically up to the beginning of the line.
+
+.. admonition:: Note
+
+    You must not use a whitespace between the tag and the minus sign.
+
+    **valid**::
+
+        {%- if foo -%}...{% endif %}
+
+    **invalid**::
+
+        {% - if foo - %}...{% endif %}
+
+
+Escaping
+--------
+
+It is sometimes desirable or even necessary to have Jinja ignore parts it
+would otherwise handle as variables or blocks.  For example if the default
+syntax is used and you want to use ``{{`` as raw string in the template and
+not start a variable you have to use a trick.
+
+The easiest way is to output the variable delimiter (``{{``) by using a
+variable expression::
+
+    {{ '{{' }}
+
+For bigger sections it makes sense to mark a block `raw`.  For example to
+put Jinja syntax as example into a template you can use this snippet::
+
+    {% raw %}
+        <ul>
+        {% for item in seq %}
+            <li>{{ item }}</li>
+        {% endfor %}
+        </ul>
+    {% endraw %}
+
+
+.. _line-statements:
+
+Line Statements
+---------------
+
+If line statements are enabled by the application it's possible to mark a
+line as a statement.  For example if the line statement prefix is configured
+to ``#`` the following two examples are equivalent::
+
+    <ul>
+    # for item in seq
+        <li>{{ item }}</li>
+    # endfor
+    </ul>
+
+    <ul>
+    {% for item in seq %}
+        <li>{{ item }}</li>
+    {% endfor %}
+    </ul>
+
+The line statement prefix can appear anywhere on the line as long as no text
+precedes it.  For better readability statements that start a block (such as
+`for`, `if`, `elif` etc.) may end with a colon::
+
+    # for item in seq:
+        ...
+    # endfor
+
+
+.. admonition:: Note
+
+    Line statements can span multiple lines if there are open parentheses,
+    braces or brackets::
+
+        <ul>
+        # for href, caption in [('index.html', 'Index'),
+                                ('about.html', 'About')]:
+            <li><a href="{{ href }}">{{ caption }}</a></li>
+        # endfor
+        </ul>
+
+Since Jinja 2.2 line-based comments are available as well.  For example if
+the line-comment prefix is configured to be ``##`` everything from ``##`` to
+the end of the line is ignored (excluding the newline sign)::
+
+    # for item in seq:
+        <li>{{ item }}</li>     ## this comment is ignored
+    # endfor
+
+
+.. _template-inheritance:
+
+Template Inheritance
+--------------------
+
+The most powerful part of Jinja is template inheritance. Template inheritance
+allows you to build a base "skeleton" template that contains all the common
+elements of your site and defines **blocks** that child templates can override.
+
+Sounds complicated but is very basic. It's easiest to understand it by starting
+with an example.
+
+
+Base Template
+~~~~~~~~~~~~~
+
+This template, which we'll call ``base.html``, defines a simple HTML skeleton
+document that you might use for a simple two-column page. It's the job of
+"child" templates to fill the empty blocks with content::
+
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+    <html lang="en">
+    <html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        {% block head %}
+        <link rel="stylesheet" href="style.css" />
+        <title>{% block title %}{% endblock %} - My Webpage</title>
+        {% endblock %}
+    </head>
+    <body>
+        <div id="content">{% block content %}{% endblock %}</div>
+        <div id="footer">
+            {% block footer %}
+            &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
+            {% endblock %}
+        </div>
+    </body>
+
+In this example, the ``{% block %}`` tags define four blocks that child templates
+can fill in. All the `block` tag does is to tell the template engine that a
+child template may override those portions of the template.
+
+Child Template
+~~~~~~~~~~~~~~
+
+A child template might look like this::
+
+    {% extends "base.html" %}
+    {% block title %}Index{% endblock %}
+    {% block head %}
+        {{ super() }}
+        <style type="text/css">
+            .important { color: #336699; }
+        </style>
+    {% endblock %}
+    {% block content %}
+        <h1>Index</h1>
+        <p class="important">
+          Welcome on my awesome homepage.
+        </p>
+    {% endblock %}
+
+The ``{% extends %}`` tag is the key here. It tells the template engine that
+this template "extends" another template.  When the template system evaluates
+this template, first it locates the parent.  The extends tag should be the
+first tag in the template.  Everything before it is printed out normally and
+may cause confusion.  For details about this behavior and how to take
+advantage of it, see :ref:`null-master-fallback`.
+
+The filename of the template depends on the template loader.  For example the
+:class:`FileSystemLoader` allows you to access other templates by giving the
+filename.  You can access templates in subdirectories with an slash::
+
+    {% extends "layout/default.html" %}
+
+But this behavior can depend on the application embedding Jinja.  Note that
+since the child template doesn't define the ``footer`` block, the value from
+the parent template is used instead.
+
+You can't define multiple ``{% block %}`` tags with the same name in the
+same template.  This limitation exists because a block tag works in "both"
+directions.  That is, a block tag doesn't just provide a hole to fill - it
+also defines the content that fills the hole in the *parent*.  If there
+were two similarly-named ``{% block %}`` tags in a template, that template's
+parent wouldn't know which one of the blocks' content to use.
+
+If you want to print a block multiple times you can however use the special
+`self` variable and call the block with that name::
+
+    <title>{% block title %}{% endblock %}</title>
+    <h1>{{ self.title() }}</h1>
+    {% block body %}{% endblock %}
+
+
+Super Blocks
+~~~~~~~~~~~~
+
+It's possible to render the contents of the parent block by calling `super`.
+This gives back the results of the parent block::
+
+    {% block sidebar %}
+        <h3>Table Of Contents</h3>
+        ...
+        {{ super() }}
+    {% endblock %}
+
+
+Named Block End-Tags
+~~~~~~~~~~~~~~~~~~~~
+
+Jinja2 allows you to put the name of the block after the end tag for better
+readability::
+
+    {% block sidebar %}
+        {% block inner_sidebar %}
+            ...
+        {% endblock inner_sidebar %}
+    {% endblock sidebar %}
+
+However the name after the `endblock` word must match the block name.
+
+
+Block Nesting and Scope
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Blocks can be nested for more complex layouts.  However per default blocks
+may not access variables from outer scopes::
+
+    {% for item in seq %}
+        <li>{% block loop_item %}{{ item }}{% endblock %}</li>
+    {% endfor %}
+
+This example would output empty ``<li>`` items because `item` is unavailable
+inside the block.  The reason for this is that if the block is replaced by
+a child template a variable would appear that was not defined in the block or
+passed to the context.
+
+Starting with Jinja 2.2 you can explicitly specify that variables are
+available in a block by setting the block to "scoped" by adding the `scoped`
+modifier to a block declaration::
+
+    {% for item in seq %}
+        <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
+    {% endfor %}
+
+When overriding a block the `scoped` modifier does not have to be provided.
+
+
+Template Objects
+~~~~~~~~~~~~~~~~
+
+.. versionchanged:: 2.4
+
+If a template object was passed to the template context you can
+extend from that object as well.  Assuming the calling code passes
+a layout template as `layout_template` to the environment, this
+code works::
+
+    {% extends layout_template %}
+
+Previously the `layout_template` variable had to be a string with
+the layout template's filename for this to work.
+
+
+HTML Escaping
+-------------
+
+When generating HTML from templates, there's always a risk that a variable will
+include characters that affect the resulting HTML.  There are two approaches:
+manually escaping each variable or automatically escaping everything by default.
+
+Jinja supports both, but what is used depends on the application configuration.
+The default configuaration is no automatic escaping for various reasons:
+
+-   escaping everything except of safe values will also mean that Jinja is
+    escaping variables known to not include HTML such as numbers which is
+    a huge performance hit.
+
+-   The information about the safety of a variable is very fragile.  It could
+    happen that by coercing safe and unsafe values the return value is double
+    escaped HTML.
+
+Working with Manual Escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If manual escaping is enabled it's **your** responsibility to escape
+variables if needed.  What to escape?  If you have a variable that *may*
+include any of the following chars (``>``, ``<``, ``&``, or ``"``) you
+**have to** escape it unless the variable contains well-formed and trusted
+HTML.  Escaping works by piping the variable through the ``|e`` filter:
+``{{ user.username|e }}``.
+
+Working with Automatic Escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When automatic escaping is enabled everything is escaped by default except
+for values explicitly marked as safe.  Those can either be marked by the
+application or in the template by using the `|safe` filter.  The main
+problem with this approach is that Python itself doesn't have the concept
+of tainted values so the information if a value is safe or unsafe can get
+lost.  If the information is lost escaping will take place which means that
+you could end up with double escaped contents.
+
+Double escaping is easy to avoid however, just rely on the tools Jinja2
+provides and don't use builtin Python constructs such as the string modulo
+operator.
+
+Functions returning template data (macros, `super`, `self.BLOCKNAME`) return
+safe markup always.
+
+String literals in templates with automatic escaping are considered unsafe
+too.  The reason for this is that the safe string is an extension to Python
+and not every library will work properly with it.
+
+
+List of Control Structures
+--------------------------
+
+A control structure refers to all those things that control the flow of a
+program - conditionals (i.e. if/elif/else), for-loops, as well as things like
+macros and blocks.  Control structures appear inside ``{% ... %}`` blocks
+in the default syntax.
+
+For
+~~~
+
+Loop over each item in a sequence.  For example, to display a list of users
+provided in a variable called `users`::
+
+    <h1>Members</h1>
+    <ul>
+    {% for user in users %}
+      <li>{{ user.username|e }}</li>
+    {% endfor %}
+    </ul>
+
+Inside of a for loop block you can access some special variables:
+
++-----------------------+---------------------------------------------------+
+| Variable              | Description                                       |
++=======================+===================================================+
+| `loop.index`          | The current iteration of the loop. (1 indexed)    |
++-----------------------+---------------------------------------------------+
+| `loop.index0`         | The current iteration of the loop. (0 indexed)    |
++-----------------------+---------------------------------------------------+
+| `loop.revindex`       | The number of iterations from the end of the loop |
+|                       | (1 indexed)                                       |
++-----------------------+---------------------------------------------------+
+| `loop.revindex0`      | The number of iterations from the end of the loop |
+|                       | (0 indexed)                                       |
++-----------------------+---------------------------------------------------+
+| `loop.first`          | True if first iteration.                          |
++-----------------------+---------------------------------------------------+
+| `loop.last`           | True if last iteration.                           |
++-----------------------+---------------------------------------------------+
+| `loop.length`         | The number of items in the sequence.              |
++-----------------------+---------------------------------------------------+
+| `loop.cycle`          | A helper function to cycle between a list of      |
+|                       | sequences.  See the explanation below.            |
++-----------------------+---------------------------------------------------+
+
+Within a for-loop, it's possible to cycle among a list of strings/variables
+each time through the loop by using the special `loop.cycle` helper::
+
+    {% for row in rows %}
+        <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
+    {% endfor %}
+
+With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound
+cycling.  For more information have a look at the :ref:`builtin-globals`.
+
+.. _loop-filtering:
+
+Unlike in Python it's not possible to `break` or `continue` in a loop.  You
+can however filter the sequence during iteration which allows you to skip
+items.  The following example skips all the users which are hidden::
+
+    {% for user in users if not user.hidden %}
+        <li>{{ user.username|e }}</li>
+    {% endfor %}
+
+The advantage is that the special `loop` variable will count correctly thus
+not counting the users not iterated over.
+
+If no iteration took place because the sequence was empty or the filtering
+removed all the items from the sequence you can render a replacement block
+by using `else`::
+
+    <ul>
+    {% for user in users %}
+        <li>{{ user.username|e }}</li>
+    {% else %}
+        <li><em>no users found</em></li>
+    {% endfor %}
+    </ul>
+
+It is also possible to use loops recursively.  This is useful if you are
+dealing with recursive data such as sitemaps.  To use loops recursively you
+basically have to add the `recursive` modifier to the loop definition and
+call the `loop` variable with the new iterable where you want to recurse.
+
+The following example implements a sitemap with recursive loops::
+
+    <ul class="sitemap">
+    {%- for item in sitemap recursive %}
+        <li><a href="{{ item.href|e }}">{{ item.title }}</a>
+        {%- if item.children -%}
+            <ul class="submenu">{{ loop(item.children) }}</ul>
+        {%- endif %}</li>
+    {%- endfor %}
+    </ul>
+
+
+If
+~~
+
+The `if` statement in Jinja is comparable with the if statements of Python.
+In the simplest form you can use it to test if a variable is defined, not
+empty or not false::
+
+    {% if users %}
+    <ul>
+    {% for user in users %}
+        <li>{{ user.username|e }}</li>
+    {% endfor %}
+    </ul>
+    {% endif %}
+
+For multiple branches `elif` and `else` can be used like in Python.  You can
+use more complex :ref:`expressions` there too::
+
+    {% if kenny.sick %}
+        Kenny is sick.
+    {% elif kenny.dead %}
+        You killed Kenny!  You bastard!!!
+    {% else %}
+        Kenny looks okay --- so far
+    {% endif %}
+
+If can also be used as :ref:`inline expression <if-expression>` and for
+:ref:`loop filtering <loop-filtering>`.
+
+
+Macros
+~~~~~~
+
+Macros are comparable with functions in regular programming languages.  They
+are useful to put often used idioms into reusable functions to not repeat
+yourself.
+
+Here a small example of a macro that renders a form element::
+
+    {% macro input(name, value='', type='text', size=20) -%}
+        <input type="{{ type }}" name="{{ name }}" value="{{
+            value|e }}" size="{{ size }}">
+    {%- endmacro %}
+
+The macro can then be called like a function in the namespace::
+
+    <p>{{ input('username') }}</p>
+    <p>{{ input('password', type='password') }}</p>
+
+If the macro was defined in a different template you have to
+:ref:`import <import>` it first.
+
+Inside macros you have access to three special variables:
+
+`varargs`
+    If more positional arguments are passed to the macro than accepted by the
+    macro they end up in the special `varargs` variable as list of values.
+
+`kwargs`
+    Like `varargs` but for keyword arguments.  All unconsumed keyword
+    arguments are stored in this special variable.
+
+`caller`
+    If the macro was called from a :ref:`call<call>` tag the caller is stored
+    in this variable as macro which can be called.
+
+Macros also expose some of their internal details.  The following attributes
+are available on a macro object:
+
+`name`
+    The name of the macro.  ``{{ input.name }}`` will print ``input``.
+
+`arguments`
+    A tuple of the names of arguments the macro accepts.
+
+`defaults`
+    A tuple of default values.
+
+`catch_kwargs`
+    This is `true` if the macro accepts extra keyword arguments (ie: accesses
+    the special `kwargs` variable).
+
+`catch_varargs`
+    This is `true` if the macro accepts extra positional arguments (ie:
+    accesses the special `varargs` variable).
+
+`caller`
+    This is `true` if the macro accesses the special `caller` variable and may
+    be called from a :ref:`call<call>` tag.
+
+If a macro name starts with an underscore it's not exported and can't
+be imported.
+
+
+.. _call:
+
+Call
+~~~~
+
+In some cases it can be useful to pass a macro to another macro.  For this
+purpose you can use the special `call` block.  The following example shows
+a macro that takes advantage of the call functionality and how it can be
+used::
+
+    {% macro render_dialog(title, class='dialog') -%}
+        <div class="{{ class }}">
+            <h2>{{ title }}</h2>
+            <div class="contents">
+                {{ caller() }}
+            </div>
+        </div>
+    {%- endmacro %}
+
+    {% call render_dialog('Hello World') %}
+        This is a simple dialog rendered by using a macro and
+        a call block.
+    {% endcall %}
+
+It's also possible to pass arguments back to the call block.  This makes it
+useful as replacement for loops.  Generally speaking a call block works
+exactly like an macro, just that it doesn't have a name.
+
+Here an example of how a call block can be used with arguments::
+
+    {% macro dump_users(users) -%}
+        <ul>
+        {%- for user in users %}
+            <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+        {%- endfor %}
+        </ul>
+    {%- endmacro %}
+
+    {% call(user) dump_users(list_of_user) %}
+        <dl>
+            <dl>Realname</dl>
+            <dd>{{ user.realname|e }}</dd>
+            <dl>Description</dl>
+            <dd>{{ user.description }}</dd>
+        </dl>
+    {% endcall %}
+
+
+Filters
+~~~~~~~
+
+Filter sections allow you to apply regular Jinja2 filters on a block of
+template data.  Just wrap the code in the special `filter` section::
+
+    {% filter upper %}
+        This text becomes uppercase
+    {% endfilter %}
+
+
+Assignments
+~~~~~~~~~~~
+
+Inside code blocks you can also assign values to variables.  Assignments at
+top level (outside of blocks, macros or loops) are exported from the template
+like top level macros and can be imported by other templates.
+
+Assignments use the `set` tag and can have multiple targets::
+
+    {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
+    {% set key, value = call_something() %}
+
+
+Extends
+~~~~~~~
+
+The `extends` tag can be used to extend a template from another one.  You
+can have multiple of them in a file but only one of them may be executed
+at the time.  See the section about :ref:`template-inheritance` above.
+
+
+Block
+~~~~~
+
+Blocks are used for inheritance and act as placeholders and replacements
+at the same time.  They are documented in detail as part of the section
+about :ref:`template-inheritance`.
+
+
+Include
+~~~~~~~
+
+The `include` statement is useful to include a template and return the
+rendered contents of that file into the current namespace::
+
+    {% include 'header.html' %}
+        Body
+    {% include 'footer.html' %}
+
+Included templates have access to the variables of the active context by
+default.  For more details about context behavior of imports and includes
+see :ref:`import-visibility`.
+
+From Jinja 2.2 onwards you can mark an include with ``ignore missing`` in
+which case Jinja will ignore the statement if the template to be ignored
+does not exist.  When combined with ``with`` or ``without context`` it has
+to be placed *before* the context visibility statement.  Here some valid
+examples::
+
+    {% include "sidebar.html" ignore missing %}
+    {% include "sidebar.html" ignore missing with context %}
+    {% include "sidebar.html" ignore missing without context %}
+
+.. versionadded:: 2.2
+
+You can also provide a list of templates that are checked for existence
+before inclusion.  The first template that exists will be included.  If
+`ignore missing` is given, it will fall back to rendering nothing if
+none of the templates exist, otherwise it will raise an exception.
+
+Example::
+
+    {% include ['page_detailed.html', 'page.html'] %}
+    {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
+
+.. versionchanged:: 2.4
+   If a template object was passed to the template context you can
+   include that object using `include`.
+
+.. _import:
+
+Import
+~~~~~~
+
+Jinja2 supports putting often used code into macros.  These macros can go into
+different templates and get imported from there.  This works similar to the
+import statements in Python.  It's important to know that imports are cached
+and imported templates don't have access to the current template variables,
+just the globals by defualt.  For more details about context behavior of
+imports and includes see :ref:`import-visibility`.
+
+There are two ways to import templates.  You can import the complete template
+into a variable or request specific macros / exported variables from it.
+
+Imagine we have a helper module that renders forms (called `forms.html`)::
+
+    {% macro input(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 %}
+
+The easiest and most flexible is importing the whole module into a variable.
+That way you can access the attributes::
+
+    {% import 'forms.html' as forms %}
+    <dl>
+        <dt>Username</dt>
+        <dd>{{ forms.input('username') }}</dd>
+        <dt>Password</dt>
+        <dd>{{ forms.input('password', type='password') }}</dd>
+    </dl>
+    <p>{{ forms.textarea('comment') }}</p>
+
+
+Alternatively you can import names from the template into the current
+namespace::
+
+    {% from 'forms.html' import input as input_field, textarea %}
+    <dl>
+        <dt>Username</dt>
+        <dd>{{ input_field('username') }}</dd>
+        <dt>Password</dt>
+        <dd>{{ input_field('password', type='password') }}</dd>
+    </dl>
+    <p>{{ textarea('comment') }}</p>
+
+Macros and variables starting with one ore more underscores are private and
+cannot be imported.
+
+.. versionchanged:: 2.4
+   If a template object was passed to the template context you can
+   import from that object.
+
+
+.. _import-visibility:
+
+Import Context Behavior
+-----------------------
+
+Per default included templates are passed the current context and imported
+templates not.  The reason for this is that imports unlike includes are
+cached as imports are often used just as a module that holds macros.
+
+This however can be changed of course explicitly.  By adding `with context`
+or `without context` to the import/include directive the current context
+can be passed to the template and caching is disabled automatically.
+
+Here two examples::
+
+    {% from 'forms.html' import input with context %}
+    {% include 'header.html' without context %}
+
+.. admonition:: Note
+
+    In Jinja 2.0 the context that was passed to the included template
+    did not include variables defined in the template.  As a matter of
+    fact this did not work::
+
+        {% for box in boxes %}
+            {% include "render_box.html" %}
+        {% endfor %}
+
+    The included template ``render_box.html`` is not able to access
+    `box` in Jinja 2.0, but in Jinja 2.1.
+
+
+.. _expressions:
+
+Expressions
+-----------
+
+Jinja allows basic expressions everywhere.  These work very similar to regular
+Python and even if you're not working with Python you should feel comfortable
+with it.
+
+Literals
+~~~~~~~~
+
+The simplest form of expressions are literals.  Literals are representations
+for Python objects such as strings and numbers.  The following literals exist:
+
+"Hello World":
+    Everything between two double or single quotes is a string.  They are
+    useful whenever you need a string in the template (for example as
+    arguments to function calls, filters or just to extend or include a
+    template).
+
+42 / 42.23:
+    Integers and floating point numbers are created by just writing the
+    number down.  If a dot is present the number is a float, otherwise an
+    integer.  Keep in mind that for Python ``42`` and ``42.0`` is something
+    different.
+
+['list', 'of', 'objects']:
+    Everything between two brackets is a list.  Lists are useful to store
+    sequential data in or to iterate over them.  For example you can easily
+    create a list of links using lists and tuples with a for loop::
+
+        <ul>
+        {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
+                                 ('downloads.html', 'Downloads')] %}
+            <li><a href="{{ href }}">{{ caption }}</a></li>
+        {% endfor %}
+        </ul>
+
+('tuple', 'of', 'values'):
+    Tuples are like lists, just that you can't modify them.  If the tuple
+    only has one item you have to end it with a comma.  Tuples are usually
+    used to represent items of two or more elements.  See the example above
+    for more details.
+
+{'dict': 'of', 'key': 'and', 'value': 'pairs'}:
+    A dict in Python is a structure that combines keys and values.  Keys must
+    be unique and always have exactly one value.  Dicts are rarely used in
+    templates, they are useful in some rare cases such as the :func:`xmlattr`
+    filter.
+
+true / false:
+    true is always true and false is always false.
+
+.. admonition:: Note
+
+    The special constants `true`, `false` and `none` are indeed lowercase.
+    Because that caused confusion in the past, when writing `True` expands
+    to an undefined variable that is considered false, all three of them can
+    be written in title case too (`True`, `False`, and `None`).  However for
+    consistency (all Jinja identifiers are lowercase) you should use the
+    lowercase versions.
+
+Math
+~~~~
+
+Jinja allows you to calculate with values.  This is rarely useful in templates
+but exists for completeness' sake.  The following operators are supported:
+
+\+
+    Adds two objects together.  Usually the objects are numbers but if both are
+    strings or lists you can concatenate them this way.  This however is not
+    the preferred way to concatenate strings!  For string concatenation have
+    a look at the ``~`` operator.  ``{{ 1 + 1 }}`` is ``2``.
+
+\-
+    Substract the second number from the first one.  ``{{ 3 - 2 }}`` is ``1``.
+
+/
+    Divide two numbers.  The return value will be a floating point number.
+    ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
+
+//
+    Divide two numbers and return the truncated integer result.
+    ``{{ 20 / 7 }}`` is ``2``.
+
+%
+    Calculate the remainder of an integer division.  ``{{ 11 % 7 }}`` is ``4``.
+
+\*
+    Multiply the left operand with the right one.  ``{{ 2 * 2 }}`` would
+    return ``4``.  This can also be used to repeat a string multiple times.
+    ``{{ '=' * 80 }}`` would print a bar of 80 equal signs.
+
+\**
+    Raise the left operand to the power of the right operand.  ``{{ 2**3 }}``
+    would return ``8``.
+
+Comparisons
+~~~~~~~~~~~
+
+==
+    Compares two objects for equality.
+
+!=
+    Compares two objects for inequality.
+
+>
+    `true` if the left hand side is greater than the right hand side.
+
+>=
+    `true` if the left hand side is greater or equal to the right hand side.
+
+<
+    `true` if the left hand side is lower than the right hand side.
+
+<=
+    `true` if the left hand side is lower or equal to the right hand side.
+
+Logic
+~~~~~
+
+For `if` statements, `for` filtering or `if` expressions it can be useful to
+combine multiple expressions:
+
+and
+    Return true if the left and the right operand is true.
+
+or
+    Return true if the left or the right operand is true.
+
+not
+    negate a statement (see below).
+
+(expr)
+    group an expression.
+
+.. admonition:: Note
+
+    The ``is`` and ``in`` operators support negation using an infix notation
+    too: ``foo is not bar`` and ``foo not in bar`` instead of ``not foo is bar``
+    and ``not foo in bar``.  All other expressions require a prefix notation:
+    ``not (foo and bar).``
+
+
+Other Operators
+~~~~~~~~~~~~~~~
+
+The following operators are very useful but don't fit into any of the other
+two categories:
+
+in
+    Perform sequence / mapping containment test.  Returns true if the left
+    operand is contained in the right.  ``{{ 1 in [1, 2, 3] }}`` would for
+    example return true.
+
+is
+    Performs a :ref:`test <tests>`.
+
+\|
+    Applies a :ref:`filter <filters>`.
+
+~
+    Converts all operands into strings and concatenates them.
+    ``{{ "Hello " ~ name ~ "!" }}`` would return (assuming `name` is
+    ``'John'``) ``Hello John!``.
+
+()
+    Call a callable: ``{{ post.render() }}``.  Inside of the parentheses you
+    can use positional arguments and keyword arguments like in python:
+    ``{{ post.render(user, full=true) }}``.
+
+. / []
+    Get an attribute of an object.  (See :ref:`variables`)
+
+
+.. _if-expression:
+
+If Expression
+~~~~~~~~~~~~~
+
+It is also possible to use inline `if` expressions.  These are useful in some
+situations.  For example you can use this to extend from one template if a
+variable is defined, otherwise from the default layout template::
+
+    {% extends layout_template if layout_template is defined else 'master.html' %}
+
+The general syntax is ``<do something> if <something is true> else <do
+something else>``.
+
+The `else` part is optional.  If not provided the else block implicitly
+evaluates into an undefined object::
+
+    {{ '[%s]' % page.title if page.title }}
+
+
+.. _builtin-filters:
+
+List of Builtin Filters
+-----------------------
+
+.. jinjafilters::
+
+
+.. _builtin-tests:
+
+List of Builtin Tests
+---------------------
+
+.. jinjatests::
+
+.. _builtin-globals:
+
+List of Global Functions
+------------------------
+
+The following functions are available in the global scope by default:
+
+.. function:: range([start,] stop[, step])
+
+    Return a list containing an arithmetic progression of integers.
+    range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
+    When step is given, it specifies the increment (or decrement).
+    For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
+    These are exactly the valid indices for a list of 4 elements.
+
+    This is useful to repeat a template block multiple times for example
+    to fill a list.  Imagine you have 7 users in the list but you want to
+    render three empty items to enforce a height with CSS::
+
+        <ul>
+        {% for user in users %}
+            <li>{{ user.username }}</li>
+        {% endfor %}
+        {% for number in range(10 - users|count) %}
+            <li class="empty"><span>...</span></li>
+        {% endfor %}
+        </ul>
+
+.. function:: lipsum(n=5, html=True, min=20, max=100)
+
+    Generates some lorem ipsum for the template.  Per default five paragraphs
+    with HTML are generated each paragraph between 20 and 100 words.  If html
+    is disabled regular text is returned.  This is useful to generate simple
+    contents for layout testing.
+
+.. function:: dict(\**items)
+
+    A convenient alternative to dict literals.  ``{'foo': 'bar'}`` is the same
+    as ``dict(foo='bar')``.
+
+.. class:: cycler(\*items)
+
+    The cycler allows you to cycle among values similar to how `loop.cycle`
+    works.  Unlike `loop.cycle` however you can use this cycler outside of
+    loops or over multiple loops.
+
+    This is for example very useful if you want to show a list of folders and
+    files, with the folders on top, but both in the same list with alternating
+    row colors.
+
+    The following example shows how `cycler` can be used::
+
+        {% set row_class = cycler('odd', 'even') %}
+        <ul class="browser">
+        {% for folder in folders %}
+          <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
+        {% endfor %}
+        {% for filename in files %}
+          <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
+        {% endfor %}
+        </ul>
+
+    A cycler has the following attributes and methods:
+
+    .. method:: reset()
+
+        Resets the cycle to the first item.
+
+    .. method:: next()
+
+        Goes one item a head and returns the then current item.
+
+    .. attribute:: current
+
+        Returns the current item.
+    
+    **new in Jinja 2.1**
+
+.. class:: joiner(sep=', ')
+
+    A tiny helper that can be use to "join" multiple sections.  A joiner is
+    passed a string and will return that string every time it's calld, except
+    the first time in which situation it returns an empty string.  You can
+    use this to join things::
+
+        {% set pipe = joiner("|") %}
+        {% if categories %} {{ pipe() }}
+            Categories: {{ categories|join(", ") }}
+        {% endif %}
+        {% if author %} {{ pipe() }}
+            Author: {{ author() }}
+        {% endif %}
+        {% if can_edit %} {{ pipe() }}
+            <a href="?action=edit">Edit</a>
+        {% endif %}
+
+    **new in Jinja 2.1**
+
+
+Extensions
+----------
+
+The following sections cover the built-in Jinja2 extensions that may be
+enabled by the application.  The application could also provide further
+extensions not covered by this documentation.  In that case there should
+be a separate document explaining the extensions.
+
+.. _i18n-in-templates:
+
+i18n
+~~~~
+
+If the i18n extension is enabled it's possible to mark parts in the template
+as translatable.  To mark a section as translatable you can use `trans`::
+
+    <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
+
+To translate a template expression --- say, using template filters or just
+accessing an attribute of an object --- you need to bind the expression to a
+name for use within the translation block::
+
+    <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
+
+If you need to bind more than one expression inside a `trans` tag, separate
+the pieces with a comma (``,``)::
+
+    {% trans book_title=book.title, author=author.name %}
+    This is {{ book_title }} by {{ author }}
+    {% endtrans %}
+
+Inside trans tags no statements are allowed, only variable tags are.
+
+To pluralize, specify both the singular and plural forms with the `pluralize`
+tag, which appears between `trans` and `endtrans`::
+
+    {% trans count=list|length %}
+    There is {{ count }} {{ name }} object.
+    {% pluralize %}
+    There are {{ count }} {{ name }} objects.
+    {% endtrans %}
+
+Per default the first variable in a block is used to determine the correct
+singular or plural form.  If that doesn't work out you can specify the name
+which should be used for pluralizing by adding it as parameter to `pluralize`::
+
+    {% trans ..., user_count=users|length %}...
+    {% pluralize user_count %}...{% endtrans %}
+
+It's also possible to translate strings in expressions.  For that purpose
+three functions exist:
+
+_   `gettext`: translate a single string
+-   `ngettext`: translate a pluralizable string
+-   `_`: alias for `gettext`
+
+For example you can print a translated string easily this way::
+
+    {{ _('Hello World!') }}
+
+To use placeholders you can use the `format` filter::
+
+    {{ _('Hello %(user)s!')|format(user=user.username) }}
+
+For multiple placeholders always use keyword arguments to `format` as other
+languages may not use the words in the same order.
+
+.. versionchanged:: 2.5
+
+If newstyle gettext calls are activated (:ref:`newstyle-gettext`), using
+placeholders is a lot easier:
+
+.. sourcecode:: html+jinja
+
+    {{ gettext('Hello World!') }}
+    {{ gettext('Hello %(name)s!', name='World') }}
+    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
+
+Note that the `ngettext` function's format string automatically recieves
+the count as `num` parameter additionally to the regular parameters.
+
+
+Expression Statement
+~~~~~~~~~~~~~~~~~~~~
+
+If the expression-statement extension is loaded a tag called `do` is available
+that works exactly like the regular variable expression (``{{ ... }}``) just
+that it doesn't print anything.  This can be used to modify lists::
+
+    {% do navigation.append('a string') %}
+
+
+Loop Controls
+~~~~~~~~~~~~~
+
+If the application enables the :ref:`loopcontrols-extension` it's possible to
+use `break` and `continue` in loops.  When `break` is reached, the loop is
+terminated, if `continue` is eached the processing is stopped and continues
+with the next iteration.
+
+Here a loop that skips every second item::
+
+    {% for user in users %}
+        {%- if loop.index is even %}{% continue %}{% endif %}
+        ...
+    {% endfor %}
+
+Likewise a look that stops processing after the 10th iteration::
+
+    {% for user in users %}
+        {%- if loop.index >= 10 %}{% break %}{% endif %}
+    {%- endfor %}
+
+
+With Statement
+~~~~~~~~~~~~~~
+
+.. versionadded:: 2.3
+
+If the application enables the :ref:`with-extension` it is possible to
+use the `with` keyword in templates.  This makes it possible to create
+a new inner scope.  Variables set within this scope are not visible
+outside of the scope.
+
+With in a nutshell::
+
+    {% with %}
+        {% set foo = 42 %}
+        {{ foo }}           foo is 42 here
+    {% endwith %}
+    foo is not visible here any longer
+
+Because it is common to set variables at the beginning of the scope
+you can do that within the with statement.  The following two examples
+are equivalent::
+
+    {% with foo = 42 %}
+        {{ foo }}
+    {% endwith %}
+
+    {% with %}
+        {% set foo = 42 %}
+        {{ foo }}
+    {% endwith %}
+
+.. _autoescape-overrides:
+
+Autoescape Extension
+--------------------
+
+.. versionadded:: 2.4
+
+If the application enables the :ref:`autoescape-extension` one can
+activate and deactivate the autoescaping from within the templates.
+
+Example::
+
+    {% autoescape true %}
+        Autoescaping is active within this block
+    {% endautoescape %}
+
+    {% autoescape false %}
+        Autoescaping is inactive within this block
+    {% endautoescape %}
+
+After the `endautoescape` the behavior is reverted to what it was before.

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/docs/tricks.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/tricks.rst b/ambari-common/src/main/python/jinja2/docs/tricks.rst
new file mode 100644
index 0000000..566575e
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/docs/tricks.rst
@@ -0,0 +1,100 @@
+Tips and Tricks
+===============
+
+.. highlight:: html+jinja
+
+This part of the documentation shows some tips and tricks for Jinja2
+templates.
+
+
+.. _null-master-fallback:
+
+Null-Master Fallback
+--------------------
+
+Jinja2 supports dynamic inheritance and does not distinguish between parent
+and child template as long as no `extends` tag is visited.  While this leads
+to the surprising behavior that everything before the first `extends` tag
+including whitespace is printed out instead of being igored, it can be used
+for a neat trick.
+
+Usually child templates extend from one template that adds a basic HTML
+skeleton.  However it's possible put the `extends` tag into an `if` tag to
+only extend from the layout template if the `standalone` variable evaluates
+to false which it does per default if it's not defined.  Additionally a very
+basic skeleton is added to the file so that if it's indeed rendered with
+`standalone` set to `True` a very basic HTML skeleton is added::
+
+    {% if not standalone %}{% extends 'master.html' %}{% endif -%}
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+    <title>{% block title %}The Page Title{% endblock %}</title>
+    <link rel="stylesheet" href="style.css" type="text/css">
+    {% block body %}
+      <p>This is the page body.</p>
+    {% endblock %}
+
+
+Alternating Rows
+----------------
+
+If you want to have different styles for each row of a table or
+list you can use the `cycle` method on the `loop` object::
+
+    <ul>
+    {% for row in rows %}
+      <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
+    {% endfor %}
+    </ul>
+
+`cycle` can take an unlimited amount of strings.  Each time this
+tag is encountered the next item from the list is rendered.
+
+
+Highlighting Active Menu Items
+------------------------------
+
+Often you want to have a navigation bar with an active navigation
+item.  This is really simple to achieve.  Because assignments outside
+of `block`\s in child templates are global and executed before the layout
+template is evaluated it's possible to define the active menu item in the
+child template::
+
+    {% extends "layout.html" %}
+    {% set active_page = "index" %}
+
+The layout template can then access `active_page`.  Additionally it makes
+sense to defined a default for that variable::
+
+    {% set navigation_bar = [
+        ('/', 'index', 'Index'),
+        ('/downloads/', 'downloads', 'Downloads'),
+        ('/about/', 'about', 'About')
+    ] -%}
+    {% set active_page = active_page|default('index') -%}
+    ...
+    <ul id="navigation">
+    {% for href, id, caption in navigation_bar %}
+      <li{% if id == active_page %} class="active"{% endif
+      %}><a href="{{ href|e }}">{{ caption|e }}</a>/li>
+    {% endfor %}
+    </ul>
+    ...
+
+.. _accessing-the-parent-loop:
+
+Accessing the parent Loop
+-------------------------
+
+The special `loop` variable always points to the innermost loop.  If it's
+desired to have access to an outer loop it's possible to alias it::
+
+    <table>
+    {% for row in table %}
+      <tr>
+      {% set rowloop = loop %}
+      {% for cell in row %}
+        <td id="cell-{{ rowloop.index }}-{{ loop.index }}>{{ cell }}</td>
+      {% endfor %}
+      </tr>
+    {% endfor %}
+    </table>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/cycle.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/cycle.py b/ambari-common/src/main/python/jinja2/examples/basic/cycle.py
new file mode 100644
index 0000000..73dd632
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/cycle.py
@@ -0,0 +1,13 @@
+from jinja2 import Environment
+
+
+env = Environment(line_statement_prefix="#", variable_start_string="${", variable_end_string="}")
+
+
+print env.from_string("""\
+<ul>
+# for item in range(10)
+    <li class="${loop.cycle('odd', 'even')}">${item}</li>
+# endfor
+</ul>\
+""").render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/debugger.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/debugger.py b/ambari-common/src/main/python/jinja2/examples/basic/debugger.py
new file mode 100644
index 0000000..4291ff7
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/debugger.py
@@ -0,0 +1,7 @@
+from jinja2 import Environment
+from jinja2.loaders import FileSystemLoader
+
+env = Environment(loader=FileSystemLoader('templates'))
+
+tmpl = env.get_template('broken.html')
+print tmpl.render(seq=[3, 2, 4, 5, 3, 2, 0, 2, 1])

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py b/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py
new file mode 100644
index 0000000..aa687c8
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/inheritance.py
@@ -0,0 +1,12 @@
+from jinja2 import Environment
+from jinja2.loaders import DictLoader
+
+
+env = Environment(loader=DictLoader({
+'a': '''[A[{% block body %}{% endblock %}]]''',
+'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''',
+'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}'''
+}))
+
+
+print env.get_template('c').render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html b/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html
new file mode 100644
index 0000000..294d5c9
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/templates/broken.html
@@ -0,0 +1,6 @@
+{% from 'subbroken.html' import may_break %}
+<ul>
+{% for item in seq %}
+  <li>{{ may_break(item) }}</li>
+{% endfor %}
+</ul>

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html b/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html
new file mode 100644
index 0000000..245eb7e
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/templates/subbroken.html
@@ -0,0 +1,3 @@
+{% macro may_break(item) -%}
+  [{{ item / 0 }}]
+{%- endmacro %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/test.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/test.py b/ambari-common/src/main/python/jinja2/examples/basic/test.py
new file mode 100644
index 0000000..b62c84f
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/test.py
@@ -0,0 +1,27 @@
+from jinja2 import Environment
+from jinja2.loaders import DictLoader
+
+env = Environment(loader=DictLoader({
+'child.html': u'''\
+{% extends master_layout or 'master.html' %}
+{% include helpers = 'helpers.html' %}
+{% macro get_the_answer() %}42{% endmacro %}
+{% title = 'Hello World' %}
+{% block body %}
+    {{ get_the_answer() }}
+    {{ helpers.conspirate() }}
+{% endblock %}
+''',
+'master.html': u'''\
+<!doctype html>
+<title>{{ title }}</title>
+{% block body %}{% endblock %}
+''',
+'helpers.html': u'''\
+{% macro conspirate() %}23{% endmacro %}
+'''
+}))
+
+
+tmpl = env.get_template("child.html")
+print tmpl.render()

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py b/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py
new file mode 100644
index 0000000..c9e8f95
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/test_filter_and_linestatements.py
@@ -0,0 +1,25 @@
+from jinja2 import Environment
+
+
+env = Environment(line_statement_prefix='%', variable_start_string="${", variable_end_string="}")
+tmpl = env.from_string("""\
+% macro foo()
+    ${caller(42)}
+% endmacro
+<ul>
+% for item in seq
+    <li>${item}</li>
+% endfor
+</ul>
+% call(var) foo()
+    [${var}]
+% endcall
+% filter escape
+    <hello world>
+    % for item in [1, 2, 3]
+      -  ${item}
+    % endfor
+% endfilter
+""")
+
+print tmpl.render(seq=range(10))

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py b/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py
new file mode 100644
index 0000000..49c2efc
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/test_loop_filter.py
@@ -0,0 +1,12 @@
+from jinja2 import Environment
+
+tmpl = Environment().from_string("""\
+<ul>
+{%- for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if item % 2 == 0 %}
+    <li>{{ loop.index }} / {{ loop.length }}: {{ item }}</li>
+{%- endfor %}
+</ul>
+if condition: {{ 1 if foo else 0 }}
+""")
+
+print tmpl.render(foo=True)

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/basic/translate.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/basic/translate.py b/ambari-common/src/main/python/jinja2/examples/basic/translate.py
new file mode 100644
index 0000000..3358765
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/basic/translate.py
@@ -0,0 +1,6 @@
+from jinja2 import Environment
+
+print Environment(extensions=['jinja2.i18n.TransExtension']).from_string("""\
+{% trans %}Hello {{ user }}!{% endtrans %}
+{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
+""").render(user="someone")

http://git-wip-us.apache.org/repos/asf/ambari/blob/570de228/ambari-common/src/main/python/jinja2/examples/bench.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/bench.py b/ambari-common/src/main/python/jinja2/examples/bench.py
new file mode 100644
index 0000000..c648dc6
--- /dev/null
+++ b/ambari-common/src/main/python/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 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/570de228/ambari-common/src/main/python/jinja2/examples/profile.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/profile.py b/ambari-common/src/main/python/jinja2/examples/profile.py
new file mode 100644
index 0000000..0c907ae
--- /dev/null
+++ b/ambari-common/src/main/python/jinja2/examples/profile.py
@@ -0,0 +1,52 @@
+try:
+    from cProfile import Profile
+except ImportError:
+    from profile import Profile
+from pstats import Stats
+from 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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/_form.html
new file mode 100644
index 0000000..9c4f710
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/django/_input_field.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/_input_field.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/_input_field.html
new file mode 100644
index 0000000..290fdbd
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/django/_textarea.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/_textarea.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/_textarea.html
new file mode 100644
index 0000000..7f10424
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/index.html
new file mode 100644
index 0000000..6f620bb
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/django/layout.html
new file mode 100644
index 0000000..60039ce
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py b/ambari-common/src/main/python/jinja2/examples/rwbench/djangoext.py
new file mode 100644
index 0000000..9e9fa6c
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html b/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/helpers.html
new file mode 100644
index 0000000..ecc6dc4
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/index.html
new file mode 100644
index 0000000..70f697d
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/genshi/layout.html
new file mode 100644
index 0000000..b12aec4
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html b/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/helpers.html
new file mode 100644
index 0000000..89976aa
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html b/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/index.html
new file mode 100644
index 0000000..b006d05
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html b/ambari-common/src/main/python/jinja2/examples/rwbench/jinja/layout.html
new file mode 100644
index 0000000..755789e
--- /dev/null
+++ b/ambari-common/src/main/python/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/570de228/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html b/ambari-common/src/main/python/jinja2/examples/rwbench/mako/helpers.html
new file mode 100644
index 0000000..a0290eb
--- /dev/null
+++ b/ambari-common/src/main/python/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>


[28/59] [abbrv] git commit: AMBARI-7147 Save button after adding new config property is disabled. (atkach)

Posted by nc...@apache.org.
AMBARI-7147 Save button after adding new config property is disabled. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7343cb2a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7343cb2a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7343cb2a

Branch: refs/heads/branch-alerts-dev
Commit: 7343cb2a8c9b4783f55072e2cf529e8ef0f0f4f8
Parents: 7490cfd
Author: atkach <at...@hortonworks.com>
Authored: Thu Sep 4 14:37:07 2014 +0300
Committer: atkach <at...@hortonworks.com>
Committed: Thu Sep 4 14:37:07 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/main/service/info/configs.js | 1 +
 ambari-web/app/models/service_config.js                 | 8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7343cb2a/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index d104083..80e92ea 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -891,6 +891,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
       componentConfig.configs.pushObject(serviceConfigProperty);
       serviceConfigProperty.validate();
     }, this);
+    componentConfig.set('initConfigsLength', componentConfig.get('configs.length'));
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/7343cb2a/ambari-web/app/models/service_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service_config.js b/ambari-web/app/models/service_config.js
index a1231d4..7d99660 100644
--- a/ambari-web/app/models/service_config.js
+++ b/ambari-web/app/models/service_config.js
@@ -27,6 +27,7 @@ App.ServiceConfig = Ember.Object.extend({
   restartRequiredMessage: '',
   restartRequiredHostsAndComponents: {},
   configGroups: [],
+  initConfigsLength: 0, // configs length after initialization in order to watch changes
   errorCount: function () {
     var overrideErrors = 0;
     this.get('configs').filterProperty("overrides").forEach(function (e) {
@@ -48,8 +49,11 @@ App.ServiceConfig = Ember.Object.extend({
   }.property('configs.@each.isValid', 'configs.@each.isVisible', 'configCategories.@each.slaveErrorCount', 'configs.@each.overrideErrorTrigger'),
 
   isPropertiesChanged: function() {
-    return this.get('configs').someProperty('isNotDefaultValue') || this.get('configs').someProperty('isOverrideChanged');
-  }.property('configs.@each.isNotDefaultValue', 'configs.@each.isOverrideChanged')
+    return this.get('configs').someProperty('isNotDefaultValue') ||
+           this.get('configs').someProperty('isOverrideChanged') ||
+           this.get('configs.length') !== this.get('initConfigsLength') ||
+           (this.get('configs.length') === this.get('initConfigsLength') && this.get('configs').someProperty('defaultValue', null));
+  }.property('configs.@each.isNotDefaultValue', 'configs.@each.isOverrideChanged', 'configs.length')
 });
 
 App.ServiceConfigCategory = Ember.Object.extend({


[39/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/api.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/api.rst b/ambari-common/src/main/python/jinja2/docs/api.rst
deleted file mode 100644
index 3bf8a94..0000000
--- a/ambari-common/src/main/python/jinja2/docs/api.rst
+++ /dev/null
@@ -1,787 +0,0 @@
-API
-===
-
-.. module:: jinja2
-    :synopsis: public Jinja2 API
-
-This document describes the API to Jinja2 and not the template language.  It
-will be most useful as reference to those implementing the template interface
-to the application and not those who are creating Jinja2 templates.
-
-Basics
-------
-
-Jinja2 uses a central object called the template :class:`Environment`.
-Instances of this class are used to store the configuration, global objects
-and are used to load templates from the file system or other locations.
-Even if you are creating templates from strings by using the constructor of
-:class:`Template` class, an environment is created automatically for you,
-albeit a shared one.
-
-Most applications will create one :class:`Environment` object on application
-initialization and use that to load templates.  In some cases it's however
-useful to have multiple environments side by side, if different configurations
-are in use.
-
-The simplest way to configure Jinja2 to load templates for your application
-looks roughly like this::
-
-    from jinja2 import Environment, PackageLoader
-    env = Environment(loader=PackageLoader('yourapplication', 'templates'))
-
-This will create a template environment with the default settings and a
-loader that looks up the templates in the `templates` folder inside the
-`yourapplication` python package.  Different loaders are available
-and you can also write your own if you want to load templates from a
-database or other resources.
-
-To load a template from this environment you just have to call the
-:meth:`get_template` method which then returns the loaded :class:`Template`::
-
-    template = env.get_template('mytemplate.html')
-
-To render it with some variables, just call the :meth:`render` method::
-
-    print template.render(the='variables', go='here')
-
-Using a template loader rather then passing strings to :class:`Template`
-or :meth:`Environment.from_string` has multiple advantages.  Besides being
-a lot easier to use it also enables template inheritance.
-
-
-Unicode
--------
-
-Jinja2 is using Unicode internally which means that you have to pass Unicode
-objects to the render function or bytestrings that only consist of ASCII
-characters.  Additionally newlines are normalized to one end of line
-sequence which is per default UNIX style (``\n``).
-
-Python 2.x supports two ways of representing string objects.  One is the
-`str` type and the other is the `unicode` type, both of which extend a type
-called `basestring`.  Unfortunately the default is `str` which should not
-be used to store text based information unless only ASCII characters are
-used.  With Python 2.6 it is possible to make `unicode` the default on a per
-module level and with Python 3 it will be the default.
-
-To explicitly use a Unicode string you have to prefix the string literal
-with a `u`: ``u'Hänsel und Gretel sagen Hallo'``.  That way Python will
-store the string as Unicode by decoding the string with the character
-encoding from the current Python module.  If no encoding is specified this
-defaults to 'ASCII' which means that you can't use any non ASCII identifier.
-
-To set a better module encoding add the following comment to the first or
-second line of the Python module using the Unicode literal::
-
-    # -*- coding: utf-8 -*-
-
-We recommend utf-8 as Encoding for Python modules and templates as it's
-possible to represent every Unicode character in utf-8 and because it's
-backwards compatible to ASCII.  For Jinja2 the default encoding of templates
-is assumed to be utf-8.
-
-It is not possible to use Jinja2 to process non-Unicode data.  The reason
-for this is that Jinja2 uses Unicode already on the language level.  For
-example Jinja2 treats the non-breaking space as valid whitespace inside
-expressions which requires knowledge of the encoding or operating on an
-Unicode string.
-
-For more details about Unicode in Python have a look at the excellent
-`Unicode documentation`_.
-
-Another important thing is how Jinja2 is handling string literals in
-templates.  A naive implementation would be using Unicode strings for
-all string literals but it turned out in the past that this is problematic
-as some libraries are typechecking against `str` explicitly.  For example
-`datetime.strftime` does not accept Unicode arguments.  To not break it
-completely Jinja2 is returning `str` for strings that fit into ASCII and
-for everything else `unicode`:
-
->>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
->>> m.a
-'foo'
->>> m.b
-u'f\xf6\xf6'
-
-
-.. _Unicode documentation: http://docs.python.org/dev/howto/unicode.html
-
-High Level API
---------------
-
-The high-level API is the API you will use in the application to load and
-render Jinja2 templates.  The :ref:`low-level-api` on the other side is only
-useful if you want to dig deeper into Jinja2 or :ref:`develop extensions
-<jinja-extensions>`.
-
-.. autoclass:: Environment([options])
-    :members: from_string, get_template, select_template,
-              get_or_select_template, join_path, extend, compile_expression
-
-    .. attribute:: shared
-
-        If a template was created by using the :class:`Template` constructor
-        an environment is created automatically.  These environments are
-        created as shared environments which means that multiple templates
-        may have the same anonymous environment.  For all shared environments
-        this attribute is `True`, else `False`.
-
-    .. attribute:: sandboxed
-
-        If the environment is sandboxed this attribute is `True`.  For the
-        sandbox mode have a look at the documentation for the
-        :class:`~jinja2.sandbox.SandboxedEnvironment`.
-
-    .. attribute:: filters
-
-        A dict of filters for this environment.  As long as no template was
-        loaded it's safe to add new filters or remove old.  For custom filters
-        see :ref:`writing-filters`.  For valid filter names have a look at
-        :ref:`identifier-naming`.
-
-    .. attribute:: tests
-
-        A dict of test functions for this environment.  As long as no
-        template was loaded it's safe to modify this dict.  For custom tests
-        see :ref:`writing-tests`.  For valid test names have a look at
-        :ref:`identifier-naming`.
-
-    .. attribute:: globals
-
-        A dict of global variables.  These variables are always available
-        in a template.  As long as no template was loaded it's safe
-        to modify this dict.  For more details see :ref:`global-namespace`.
-        For valid object names have a look at :ref:`identifier-naming`.
-
-    .. automethod:: overlay([options])
-
-    .. method:: undefined([hint, obj, name, exc])
-
-        Creates a new :class:`Undefined` object for `name`.  This is useful
-        for filters or functions that may return undefined objects for
-        some operations.  All parameters except of `hint` should be provided
-        as keyword parameters for better readability.  The `hint` is used as
-        error message for the exception if provided, otherwise the error
-        message will be generated from `obj` and `name` automatically.  The exception
-        provided as `exc` is raised if something with the generated undefined
-        object is done that the undefined object does not allow.  The default
-        exception is :exc:`UndefinedError`.  If a `hint` is provided the
-        `name` may be ommited.
-
-        The most common way to create an undefined object is by providing
-        a name only::
-
-            return environment.undefined(name='some_name')
-
-        This means that the name `some_name` is not defined.  If the name
-        was from an attribute of an object it makes sense to tell the
-        undefined object the holder object to improve the error message::
-
-            if not hasattr(obj, 'attr'):
-                return environment.undefined(obj=obj, name='attr')
-
-        For a more complex example you can provide a hint.  For example
-        the :func:`first` filter creates an undefined object that way::
-
-            return environment.undefined('no first item, sequence was empty')            
-
-        If it the `name` or `obj` is known (for example because an attribute
-        was accessed) it shold be passed to the undefined object, even if
-        a custom `hint` is provided.  This gives undefined objects the
-        possibility to enhance the error message.
-
-.. autoclass:: Template
-    :members: module, make_module
-
-    .. attribute:: globals
-
-        The dict with the globals of that template.  It's unsafe to modify
-        this dict as it may be shared with other templates or the environment
-        that loaded the template.
-
-    .. attribute:: name
-
-        The loading name of the template.  If the template was loaded from a
-        string this is `None`.
-
-    .. attribute:: filename
-
-        The filename of the template on the file system if it was loaded from
-        there.  Otherwise this is `None`.
-
-    .. automethod:: render([context])
-
-    .. automethod:: generate([context])
-
-    .. automethod:: stream([context])
-
-
-.. autoclass:: jinja2.environment.TemplateStream()
-    :members: disable_buffering, enable_buffering, dump
-
-
-Autoescaping
-------------
-
-.. versionadded:: 2.4
-
-As of Jinja 2.4 the preferred way to do autoescaping is to enable the
-:ref:`autoescape-extension` and to configure a sensible default for
-autoescaping.  This makes it possible to enable and disable autoescaping
-on a per-template basis (HTML versus text for instance).
-
-Here a recommended setup that enables autoescaping for templates ending
-in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
-for all other extensions::
-
-    def guess_autoescape(template_name):
-        if template_name is None or '.' not in template_name:
-            return False
-        ext = template_name.rsplit('.', 1)[1]
-        return ext in ('html', 'htm', 'xml')
-
-    env = Environment(autoescape=guess_autoescape,
-                      loader=PackageLoader('mypackage'),
-                      extensions=['jinja2.ext.autoescape'])
-
-When implementing a guessing autoescape function, make sure you also
-accept `None` as valid template name.  This will be passed when generating
-templates from strings.
-
-Inside the templates the behaviour can be temporarily changed by using
-the `autoescape` block (see :ref:`autoescape-overrides`).
-
-
-.. _identifier-naming:
-
-Notes on Identifiers
---------------------
-
-Jinja2 uses the regular Python 2.x naming rules.  Valid identifiers have to
-match ``[a-zA-Z_][a-zA-Z0-9_]*``.  As a matter of fact non ASCII characters
-are currently not allowed.  This limitation will probably go away as soon as
-unicode identifiers are fully specified for Python 3.
-
-Filters and tests are looked up in separate namespaces and have slightly
-modified identifier syntax.  Filters and tests may contain dots to group
-filters and tests by topic.  For example it's perfectly valid to add a
-function into the filter dict and call it `to.unicode`.  The regular
-expression for filter and test identifiers is
-``[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*```.
-
-
-Undefined Types
----------------
-
-These classes can be used as undefined types.  The :class:`Environment`
-constructor takes an `undefined` parameter that can be one of those classes
-or a custom subclass of :class:`Undefined`.  Whenever the template engine is
-unable to look up a name or access an attribute one of those objects is
-created and returned.  Some operations on undefined values are then allowed,
-others fail.
-
-The closest to regular Python behavior is the `StrictUndefined` which
-disallows all operations beside testing if it's an undefined object.
-
-.. autoclass:: jinja2.Undefined()
-
-    .. attribute:: _undefined_hint
-
-        Either `None` or an unicode string with the error message for
-        the undefined object.
-
-    .. attribute:: _undefined_obj
-
-        Either `None` or the owner object that caused the undefined object
-        to be created (for example because an attribute does not exist).
-
-    .. attribute:: _undefined_name
-
-        The name for the undefined variable / attribute or just `None`
-        if no such information exists.
-
-    .. attribute:: _undefined_exception
-
-        The exception that the undefined object wants to raise.  This
-        is usually one of :exc:`UndefinedError` or :exc:`SecurityError`.
-
-    .. method:: _fail_with_undefined_error(\*args, \**kwargs)
-
-        When called with any arguments this method raises
-        :attr:`_undefined_exception` with an error message generated
-        from the undefined hints stored on the undefined object.
-
-.. autoclass:: jinja2.DebugUndefined()
-
-.. autoclass:: jinja2.StrictUndefined()
-
-Undefined objects are created by calling :attr:`undefined`.
-
-.. admonition:: Implementation
-
-    :class:`Undefined` objects are implemented by overriding the special
-    `__underscore__` methods.  For example the default :class:`Undefined`
-    class implements `__unicode__` in a way that it returns an empty
-    string, however `__int__` and others still fail with an exception.  To
-    allow conversion to int by returning ``0`` you can implement your own::
-
-        class NullUndefined(Undefined):
-            def __int__(self):
-                return 0
-            def __float__(self):
-                return 0.0
-
-    To disallow a method, just override it and raise
-    :attr:`~Undefined._undefined_exception`.  Because this is a very common
-    idom in undefined objects there is the helper method
-    :meth:`~Undefined._fail_with_undefined_error` that does the error raising
-    automatically.  Here a class that works like the regular :class:`Undefined`
-    but chokes on iteration::
-
-        class NonIterableUndefined(Undefined):
-            __iter__ = Undefined._fail_with_undefined_error
-
-
-The Context
------------
-
-.. autoclass:: jinja2.runtime.Context()
-    :members: resolve, get_exported, get_all
-
-    .. attribute:: parent
-
-        A dict of read only, global variables the template looks up.  These
-        can either come from another :class:`Context`, from the
-        :attr:`Environment.globals` or :attr:`Template.globals` or points
-        to a dict created by combining the globals with the variables
-        passed to the render function.  It must not be altered.
-
-    .. attribute:: vars
-
-        The template local variables.  This list contains environment and
-        context functions from the :attr:`parent` scope as well as local
-        modifications and exported variables from the template.  The template
-        will modify this dict during template evaluation but filters and
-        context functions are not allowed to modify it.
-
-    .. attribute:: environment
-
-        The environment that loaded the template.
-
-    .. attribute:: exported_vars
-
-        This set contains all the names the template exports.  The values for
-        the names are in the :attr:`vars` dict.  In order to get a copy of the
-        exported variables as dict, :meth:`get_exported` can be used.
-
-    .. attribute:: name
-
-        The load name of the template owning this context.
-
-    .. attribute:: blocks
-
-        A dict with the current mapping of blocks in the template.  The keys
-        in this dict are the names of the blocks, and the values a list of
-        blocks registered.  The last item in each list is the current active
-        block (latest in the inheritance chain).
-
-    .. attribute:: eval_ctx
-
-        The current :ref:`eval-context`.
-
-    .. automethod:: jinja2.runtime.Context.call(callable, \*args, \**kwargs)
-
-
-.. admonition:: Implementation
-
-    Context is immutable for the same reason Python's frame locals are
-    immutable inside functions.  Both Jinja2 and Python are not using the
-    context / frame locals as data storage for variables but only as primary
-    data source.
-
-    When a template accesses a variable the template does not define, Jinja2
-    looks up the variable in the context, after that the variable is treated
-    as if it was defined in the template.
-
-
-.. _loaders:
-
-Loaders
--------
-
-Loaders are responsible for loading templates from a resource such as the
-file system.  The environment will keep the compiled modules in memory like
-Python's `sys.modules`.  Unlike `sys.modules` however this cache is limited in
-size by default and templates are automatically reloaded.
-All loaders are subclasses of :class:`BaseLoader`.  If you want to create your
-own loader, subclass :class:`BaseLoader` and override `get_source`.
-
-.. autoclass:: jinja2.BaseLoader
-    :members: get_source, load
-
-Here a list of the builtin loaders Jinja2 provides:
-
-.. autoclass:: jinja2.FileSystemLoader
-
-.. autoclass:: jinja2.PackageLoader
-
-.. autoclass:: jinja2.DictLoader
-
-.. autoclass:: jinja2.FunctionLoader
-
-.. autoclass:: jinja2.PrefixLoader
-
-.. autoclass:: jinja2.ChoiceLoader
-
-
-.. _bytecode-cache:
-
-Bytecode Cache
---------------
-
-Jinja 2.1 and higher support external bytecode caching.  Bytecode caches make
-it possible to store the generated bytecode on the file system or a different
-location to avoid parsing the templates on first use.
-
-This is especially useful if you have a web application that is initialized on
-the first request and Jinja compiles many templates at once which slows down
-the application.
-
-To use a bytecode cache, instanciate it and pass it to the :class:`Environment`.
-
-.. autoclass:: jinja2.BytecodeCache
-    :members: load_bytecode, dump_bytecode, clear
-
-.. autoclass:: jinja2.bccache.Bucket
-    :members: write_bytecode, load_bytecode, bytecode_from_string,
-              bytecode_to_string, reset
-
-    .. attribute:: environment
-
-        The :class:`Environment` that created the bucket.
-
-    .. attribute:: key
-
-        The unique cache key for this bucket
-
-    .. attribute:: code
-
-        The bytecode if it's loaded, otherwise `None`.
-
-
-Builtin bytecode caches:
-
-.. autoclass:: jinja2.FileSystemBytecodeCache
-
-.. autoclass:: jinja2.MemcachedBytecodeCache
-
-
-Utilities
----------
-
-These helper functions and classes are useful if you add custom filters or
-functions to a Jinja2 environment.
-
-.. autofunction:: jinja2.environmentfilter
-
-.. autofunction:: jinja2.contextfilter
-
-.. autofunction:: jinja2.evalcontextfilter
-
-.. autofunction:: jinja2.environmentfunction
-
-.. autofunction:: jinja2.contextfunction
-
-.. autofunction:: jinja2.evalcontextfunction
-
-.. function:: escape(s)
-
-    Convert the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in string `s`
-    to HTML-safe sequences.  Use this if you need to display text that might
-    contain such characters in HTML.  This function will not escaped objects
-    that do have an HTML representation such as already escaped data.
-
-    The return value is a :class:`Markup` string.
-
-.. autofunction:: jinja2.clear_caches
-
-.. autofunction:: jinja2.is_undefined
-
-.. autoclass:: jinja2.Markup([string])
-    :members: escape, unescape, striptags
-
-.. admonition:: Note
-
-    The Jinja2 :class:`Markup` class is compatible with at least Pylons and
-    Genshi.  It's expected that more template engines and framework will pick
-    up the `__html__` concept soon.
-
-
-Exceptions
-----------
-
-.. autoexception:: jinja2.TemplateError
-
-.. autoexception:: jinja2.UndefinedError
-
-.. autoexception:: jinja2.TemplateNotFound
-
-.. autoexception:: jinja2.TemplatesNotFound
-
-.. autoexception:: jinja2.TemplateSyntaxError
-
-    .. attribute:: message
-
-        The error message as utf-8 bytestring.
-
-    .. attribute:: lineno
-
-        The line number where the error occurred
-
-    .. attribute:: name
-
-        The load name for the template as unicode string.
-
-    .. attribute:: filename
-
-        The filename that loaded the template as bytestring in the encoding
-        of the file system (most likely utf-8 or mbcs on Windows systems).
-
-    The reason why the filename and error message are bytestrings and not
-    unicode strings is that Python 2.x is not using unicode for exceptions
-    and tracebacks as well as the compiler.  This will change with Python 3.
-
-.. autoexception:: jinja2.TemplateAssertionError
-
-
-.. _writing-filters:
-
-Custom Filters
---------------
-
-Custom filters are just regular Python functions that take the left side of
-the filter as first argument and the the arguments passed to the filter as
-extra arguments or keyword arguments.
-
-For example in the filter ``{{ 42|myfilter(23) }}`` the function would be
-called with ``myfilter(42, 23)``.  Here for example a simple filter that can
-be applied to datetime objects to format them::
-
-    def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
-        return value.strftime(format)
-
-You can register it on the template environment by updating the
-:attr:`~Environment.filters` dict on the environment::
-
-    environment.filters['datetimeformat'] = datetimeformat
-
-Inside the template it can then be used as follows:
-
-.. sourcecode:: jinja
-
-    written on: {{ article.pub_date|datetimeformat }}
-    publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}
-
-Filters can also be passed the current template context or environment.  This
-is useful if a filter wants to return an undefined value or check the current
-:attr:`~Environment.autoescape` setting.  For this purpose three decorators
-exist: :func:`environmentfilter`, :func:`contextfilter` and
-:func:`evalcontextfilter`.
-
-Here a small example filter that breaks a text into HTML line breaks and
-paragraphs and marks the return value as safe HTML string if autoescaping is
-enabled::
-
-    import re
-    from jinja2 import environmentfilter, Markup, escape
-
-    _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
-
-    @evalcontextfilter
-    def nl2br(eval_ctx, value):
-        result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
-                              for p in _paragraph_re.split(escape(value)))
-        if eval_ctx.autoescape:
-            result = Markup(result)
-        return result
-
-Context filters work the same just that the first argument is the current
-active :class:`Context` rather then the environment.
-
-
-.. _eval-context:
-
-Evaluation Context
-------------------
-
-The evaluation context (short eval context or eval ctx) is a new object
-introducted in Jinja 2.4 that makes it possible to activate and deactivate
-compiled features at runtime.
-
-Currently it is only used to enable and disable the automatic escaping but
-can be used for extensions as well.
-
-In previous Jinja versions filters and functions were marked as
-environment callables in order to check for the autoescape status from the
-environment.  In new versions it's encouraged to check the setting from the
-evaluation context instead.
-
-Previous versions::
-
-    @environmentfilter
-    def filter(env, value):
-        result = do_something(value)
-        if env.autoescape:
-            result = Markup(result)
-        return result
-
-In new versions you can either use a :func:`contextfilter` and access the
-evaluation context from the actual context, or use a
-:func:`evalcontextfilter` which directly passes the evaluation context to
-the function::
-
-    @contextfilter
-    def filter(context, value):
-        result = do_something(value)
-        if context.eval_ctx.autoescape:
-            result = Markup(result)
-        return result
-
-    @evalcontextfilter
-    def filter(eval_ctx, value):
-        result = do_something(value)
-        if eval_ctx.autoescape:
-            result = Markup(result)
-        return result
-
-The evaluation context must not be modified at runtime.  Modifications
-must only happen with a :class:`nodes.EvalContextModifier` and
-:class:`nodes.ScopedEvalContextModifier` from an extension, not on the
-eval context object itself.
-
-.. autoclass:: jinja2.nodes.EvalContext
-
-   .. attribute:: autoescape
-
-      `True` or `False` depending on if autoescaping is active or not.
-
-   .. attribute:: volatile
-
-      `True` if the compiler cannot evaluate some expressions at compile
-      time.  At runtime this should always be `False`.
-
-
-.. _writing-tests:
-
-Custom Tests
-------------
-
-Tests work like filters just that there is no way for a test to get access
-to the environment or context and that they can't be chained.  The return
-value of a test should be `True` or `False`.  The purpose of a test is to
-give the template designers the possibility to perform type and conformability
-checks.
-
-Here a simple test that checks if a variable is a prime number::
-
-    import math
-
-    def is_prime(n):
-        if n == 2:
-            return True
-        for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
-            if n % i == 0:
-                return False
-        return True
-        
-
-You can register it on the template environment by updating the
-:attr:`~Environment.tests` dict on the environment::
-
-    environment.tests['prime'] = is_prime
-
-A template designer can then use the test like this:
-
-.. sourcecode:: jinja
-
-    {% if 42 is prime %}
-        42 is a prime number
-    {% else %}
-        42 is not a prime number
-    {% endif %}
-
-
-.. _global-namespace:
-
-The Global Namespace
---------------------
-
-Variables stored in the :attr:`Environment.globals` dict are special as they
-are available for imported templates too, even if they are imported without
-context.  This is the place where you can put variables and functions
-that should be available all the time.  Additionally :attr:`Template.globals`
-exist that are variables available to a specific template that are available
-to all :meth:`~Template.render` calls.
-
-
-.. _low-level-api:
-
-Low Level API
--------------
-
-The low level API exposes functionality that can be useful to understand some
-implementation details, debugging purposes or advanced :ref:`extension
-<jinja-extensions>` techniques.  Unless you know exactly what you are doing we
-don't recommend using any of those.
-
-.. automethod:: Environment.lex
-
-.. automethod:: Environment.parse
-
-.. automethod:: Environment.preprocess
-
-.. automethod:: Template.new_context
-
-.. method:: Template.root_render_func(context)
-
-    This is the low level render function.  It's passed a :class:`Context`
-    that has to be created by :meth:`new_context` of the same template or
-    a compatible template.  This render function is generated by the
-    compiler from the template code and returns a generator that yields
-    unicode strings.
-
-    If an exception in the template code happens the template engine will
-    not rewrite the exception but pass through the original one.  As a
-    matter of fact this function should only be called from within a
-    :meth:`render` / :meth:`generate` / :meth:`stream` call.
-
-.. attribute:: Template.blocks
-
-    A dict of block render functions.  Each of these functions works exactly
-    like the :meth:`root_render_func` with the same limitations.
-
-.. attribute:: Template.is_up_to_date
-
-    This attribute is `False` if there is a newer version of the template
-    available, otherwise `True`.
-
-.. admonition:: Note
-
-    The low-level API is fragile.  Future Jinja2 versions will try not to
-    change it in a backwards incompatible way but modifications in the Jinja2
-    core may shine through.  For example if Jinja2 introduces a new AST node
-    in later versions that may be returned by :meth:`~Environment.parse`.
-
-The Meta API
-------------
-
-.. versionadded:: 2.2
-
-The meta API returns some information about abstract syntax trees that
-could help applications to implement more advanced template concepts.  All
-the functions of the meta API operate on an abstract syntax tree as
-returned by the :meth:`Environment.parse` method.
-
-.. autofunction:: jinja2.meta.find_undeclared_variables
-
-.. autofunction:: jinja2.meta.find_referenced_templates

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/cache_extension.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/cache_extension.py b/ambari-common/src/main/python/jinja2/docs/cache_extension.py
deleted file mode 100644
index 8fdefb5..0000000
--- a/ambari-common/src/main/python/jinja2/docs/cache_extension.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from jinja2 import nodes
-from jinja2.ext import Extension
-
-
-class FragmentCacheExtension(Extension):
-    # a set of names that trigger the extension.
-    tags = set(['cache'])
-
-    def __init__(self, environment):
-        super(FragmentCacheExtension, self).__init__(environment)
-
-        # add the defaults to the environment
-        environment.extend(
-            fragment_cache_prefix='',
-            fragment_cache=None
-        )
-
-    def parse(self, parser):
-        # the first token is the token that started the tag.  In our case
-        # we only listen to ``'cache'`` so this will be a name token with
-        # `cache` as value.  We get the line number so that we can give
-        # that line number to the nodes we create by hand.
-        lineno = parser.stream.next().lineno
-
-        # now we parse a single expression that is used as cache key.
-        args = [parser.parse_expression()]
-
-        # if there is a comma, the user provided a timeout.  If not use
-        # None as second parameter.
-        if parser.stream.skip_if('comma'):
-            args.append(parser.parse_expression())
-        else:
-            args.append(nodes.Const(None))
-
-        # now we parse the body of the cache block up to `endcache` and
-        # drop the needle (which would always be `endcache` in that case)
-        body = parser.parse_statements(['name:endcache'], drop_needle=True)
-
-        # now return a `CallBlock` node that calls our _cache_support
-        # helper method on this extension.
-        return nodes.CallBlock(self.call_method('_cache_support', args),
-                               [], [], body).set_lineno(lineno)
-
-    def _cache_support(self, name, timeout, caller):
-        """Helper callback."""
-        key = self.environment.fragment_cache_prefix + name
-
-        # try to load the block from the cache
-        # if there is no fragment in the cache, render it and store
-        # it in the cache.
-        rv = self.environment.fragment_cache.get(key)
-        if rv is not None:
-            return rv
-        rv = caller()
-        self.environment.fragment_cache.add(key, rv, timeout)
-        return rv

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/changelog.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/changelog.rst b/ambari-common/src/main/python/jinja2/docs/changelog.rst
deleted file mode 100644
index 9f11484..0000000
--- a/ambari-common/src/main/python/jinja2/docs/changelog.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-.. module:: jinja2
-
-.. include:: ../CHANGES

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/conf.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/conf.py b/ambari-common/src/main/python/jinja2/docs/conf.py
deleted file mode 100644
index ba90c49..0000000
--- a/ambari-common/src/main/python/jinja2/docs/conf.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Jinja2 documentation build configuration file, created by
-# sphinx-quickstart on Sun Apr 27 21:42:41 2008.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
-#
-# All configuration values have a default value; values that are commented out
-# serve to show the default value.
-
-import sys, os
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-sys.path.append(os.path.dirname(os.path.abspath(__file__)))
-
-# General configuration
-# ---------------------
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'jinjaext']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General substitutions.
-project = 'Jinja2'
-copyright = '2008, Armin Ronacher'
-
-# The default replacements for |version| and |release|, also used in various
-# other places throughout the built documents.
-#
-# The short X.Y version.
-version = '2.0'
-# The full version, including alpha/beta/rc tags.
-release = '2.0'
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%B %d, %Y'
-
-# List of documents that shouldn't be included in the build.
-#unused_docs = []
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'jinjaext.JinjaStyle'
-
-
-# Options for HTML output
-# -----------------------
-
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-html_style = 'style.css'
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# no modindex
-html_use_modindex = False
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.
-#html_use_opensearch = False
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'Jinja2doc'
-
-
-# Options for LaTeX output
-# ------------------------
-
-# The paper size ('letter' or 'a4').
-latex_paper_size = 'a4'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, document class [howto/manual]).
-latex_documents = [
-  ('index', 'Jinja2.tex', 'Jinja2 Documentation', 'Armin Ronacher', 'manual', 'toctree_only'),
-]
-
-# Additional stuff for the LaTeX preamble.
-latex_preamble = '''
-\usepackage{palatino}
-\definecolor{TitleColor}{rgb}{0.7,0,0}
-\definecolor{InnerLinkColor}{rgb}{0.7,0,0}
-\definecolor{OuterLinkColor}{rgb}{0.8,0,0}
-\definecolor{VerbatimColor}{rgb}{0.985,0.985,0.985}
-\definecolor{VerbatimBorderColor}{rgb}{0.8,0.8,0.8}
-'''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-latex_use_modindex = False

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/extensions.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/extensions.rst b/ambari-common/src/main/python/jinja2/docs/extensions.rst
deleted file mode 100644
index c6b6ec9..0000000
--- a/ambari-common/src/main/python/jinja2/docs/extensions.rst
+++ /dev/null
@@ -1,347 +0,0 @@
-.. _jinja-extensions:
-
-Extensions
-==========
-
-Jinja2 supports extensions that can add extra filters, tests, globals or even
-extend the parser.  The main motivation of extensions is it to move often used
-code into a reusable class like adding support for internationalization.
-
-
-Adding Extensions
------------------
-
-Extensions are added to the Jinja2 environment at creation time.  Once the
-environment is created additional extensions cannot be added.  To add an
-extension pass a list of extension classes or import paths to the
-`environment` parameter of the :class:`Environment` constructor.  The following
-example creates a Jinja2 environment with the i18n extension loaded::
-
-    jinja_env = Environment(extensions=['jinja2.ext.i18n'])
-
-
-.. _i18n-extension:
-
-i18n Extension
---------------
-
-**Import name:** `jinja2.ext.i18n`
-
-Jinja2 currently comes with one extension, the i18n extension.  It can be
-used in combination with `gettext`_ or `babel`_.  If the i18n extension is
-enabled Jinja2 provides a `trans` statement that marks the wrapped string as
-translatable and calls `gettext`.
-
-After enabling dummy `_` function that forwards calls to `gettext` is added
-to the environment globals.  An internationalized application then has to
-provide at least an `gettext` and optoinally a `ngettext` function into the
-namespace.  Either globally or for each rendering.
-
-Environment Methods
-~~~~~~~~~~~~~~~~~~~
-
-After enabling of the extension the environment provides the following
-additional methods:
-
-.. method:: jinja2.Environment.install_gettext_translations(translations, newstyle=False)
-
-    Installs a translation globally for that environment.  The tranlations
-    object provided must implement at least `ugettext` and `ungettext`.
-    The `gettext.NullTranslations` and `gettext.GNUTranslations` classes
-    as well as `Babel`_\s `Translations` class are supported.
-
-    .. versionchanged:: 2.5 newstyle gettext added
-
-.. method:: jinja2.Environment.install_null_translations(newstyle=False)
-
-    Install dummy gettext functions.  This is useful if you want to prepare
-    the application for internationalization but don't want to implement the
-    full internationalization system yet.
-
-    .. versionchanged:: 2.5 newstyle gettext added
-
-.. method:: jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False)
-
-    Installs the given `gettext` and `ngettext` callables into the
-    environment as globals.  They are supposed to behave exactly like the
-    standard library's :func:`gettext.ugettext` and
-    :func:`gettext.ungettext` functions.
-
-    If `newstyle` is activated, the callables are wrapped to work like
-    newstyle callables.  See :ref:`newstyle-gettext` for more information.
-
-    .. versionadded:: 2.5
-
-.. method:: jinja2.Environment.uninstall_gettext_translations()
-
-    Uninstall the translations again.
-
-.. method:: jinja2.Environment.extract_translations(source)
-
-    Extract localizable strings from the given template node or source.
-
-    For every string found this function yields a ``(lineno, function,
-    message)`` tuple, where:
-
-    * `lineno` is the number of the line on which the string was found,
-    * `function` is the name of the `gettext` function used (if the
-      string was extracted from embedded Python code), and
-    *  `message` is the string itself (a `unicode` object, or a tuple
-       of `unicode` objects for functions with multiple string arguments).
-
-    If `Babel`_ is installed :ref:`the babel integration <babel-integration>`
-    can be used to extract strings for babel.
-
-For a web application that is available in multiple languages but gives all
-the users the same language (for example a multilingual forum software
-installed for a French community) may load the translations once and add the
-translation methods to the environment at environment generation time::
-
-    translations = get_gettext_translations()
-    env = Environment(extensions=['jinja2.ext.i18n'])
-    env.install_gettext_translations(translations)
-
-The `get_gettext_translations` function would return the translator for the
-current configuration.  (For example by using `gettext.find`)
-
-The usage of the `i18n` extension for template designers is covered as part
-:ref:`of the template documentation <i18n-in-templates>`.
-
-.. _gettext: http://docs.python.org/dev/library/gettext
-.. _Babel: http://babel.edgewall.org/
-
-.. _newstyle-gettext:
-
-Newstyle Gettext
-~~~~~~~~~~~~~~~~
-
-.. versionadded:: 2.5
-
-Starting with version 2.5 you can use newstyle gettext calls.  These are
-inspired by trac's internal gettext functions and are fully supported by
-the babel extraction tool.  They might not work as expected by other
-extraction tools in case you are not using Babel's.
-
-What's the big difference between standard and newstyle gettext calls?  In
-general they are less to type and less error prone.  Also if they are used
-in an autoescaping environment they better support automatic escaping.
-Here some common differences between old and new calls:
-
-standard gettext:
-
-.. sourcecode:: html+jinja
-
-    {{ gettext('Hello World!') }}
-    {{ gettext('Hello %(name)s!')|format(name='World') }}
-    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count)|format(
-        num=apples|count
-    )}}
-
-newstyle gettext looks like this instead:
-
-.. sourcecode:: html+jinja
-
-    {{ gettext('Hello World!') }}
-    {{ gettext('Hello %(name)s!', name='World') }}
-    {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
-
-The advantages of newstyle gettext is that you have less to type and that
-named placeholders become mandatory.  The latter sounds like a
-disadvantage but solves a lot of troubles translators are often facing
-when they are unable to switch the positions of two placeholder.  With
-newstyle gettext, all format strings look the same.
-
-Furthermore with newstyle gettext, string formatting is also used if no
-placeholders are used which makes all strings behave exactly the same.
-Last but not least are newstyle gettext calls able to properly mark
-strings for autoescaping which solves lots of escaping related issues many
-templates are experiencing over time when using autoescaping.
-
-Expression Statement
---------------------
-
-**Import name:** `jinja2.ext.do`
-
-The "do" aka expression-statement extension adds a simple `do` tag to the
-template engine that works like a variable expression but ignores the
-return value.
-
-.. _loopcontrols-extension:
-
-Loop Controls
--------------
-
-**Import name:** `jinja2.ext.loopcontrols`
-
-This extension adds support for `break` and `continue` in loops.  After
-enabling Jinja2 provides those two keywords which work exactly like in
-Python.
-
-.. _with-extension:
-
-With Statement
---------------
-
-**Import name:** `jinja2.ext.with_`
-
-.. versionadded:: 2.3
-
-This extension adds support for the with keyword.  Using this keyword it
-is possible to enforce a nested scope in a template.  Variables can be
-declared directly in the opening block of the with statement or using a
-standard `set` statement directly within.
-
-.. _autoescape-extension:
-
-Autoescape Extension
---------------------
-
-**Import name:** `jinja2.ext.autoescape`
-
-.. versionadded:: 2.4
-
-The autoescape extension allows you to toggle the autoescape feature from
-within the template.  If the environment's :attr:`~Environment.autoescape`
-setting is set to `False` it can be activated, if it's `True` it can be
-deactivated.  The setting overriding is scoped.
-
-
-.. _writing-extensions:
-
-Writing Extensions
-------------------
-
-.. module:: jinja2.ext
-
-By writing extensions you can add custom tags to Jinja2.  This is a non trival
-task and usually not needed as the default tags and expressions cover all
-common use cases.  The i18n extension is a good example of why extensions are
-useful, another one would be fragment caching.
-
-When writing extensions you have to keep in mind that you are working with the
-Jinja2 template compiler which does not validate the node tree you are possing
-to it.  If the AST is malformed you will get all kinds of compiler or runtime
-errors that are horrible to debug.  Always make sure you are using the nodes
-you create correctly.  The API documentation below shows which nodes exist and
-how to use them.
-
-Example Extension
-~~~~~~~~~~~~~~~~~
-
-The following example implements a `cache` tag for Jinja2 by using the
-`Werkzeug`_ caching contrib module:
-
-.. literalinclude:: cache_extension.py
-    :language: python
-
-And here is how you use it in an environment::
-
-    from jinja2 import Environment
-    from werkzeug.contrib.cache import SimpleCache
-
-    env = Environment(extensions=[FragmentCacheExtension])
-    env.fragment_cache = SimpleCache()
-
-Inside the template it's then possible to mark blocks as cacheable.  The
-following example caches a sidebar for 300 seconds:
-
-.. sourcecode:: html+jinja
-
-    {% cache 'sidebar', 300 %}
-    <div class="sidebar">
-        ...
-    </div>
-    {% endcache %}
-
-.. _Werkzeug: http://werkzeug.pocoo.org/
-
-Extension API
-~~~~~~~~~~~~~
-
-Extensions always have to extend the :class:`jinja2.ext.Extension` class:
-
-.. autoclass:: Extension
-    :members: preprocess, filter_stream, parse, attr, call_method
-
-    .. attribute:: identifier
-
-        The identifier of the extension.  This is always the true import name
-        of the extension class and must not be changed.
-
-    .. attribute:: tags
-
-        If the extension implements custom tags this is a set of tag names
-        the extension is listening for.
-
-Parser API
-~~~~~~~~~~
-
-The parser passed to :meth:`Extension.parse` provides ways to parse
-expressions of different types.  The following methods may be used by
-extensions:
-
-.. autoclass:: jinja2.parser.Parser
-    :members: parse_expression, parse_tuple, parse_assign_target,
-              parse_statements, free_identifier, fail
-
-    .. attribute:: filename
-
-        The filename of the template the parser processes.  This is **not**
-        the load name of the template.  For the load name see :attr:`name`.
-        For templates that were not loaded form the file system this is
-        `None`.
-
-    .. attribute:: name
-
-        The load name of the template.
-
-    .. attribute:: stream
-
-        The current :class:`~jinja2.lexer.TokenStream`
-
-.. autoclass:: jinja2.lexer.TokenStream
-   :members: push, look, eos, skip, next, next_if, skip_if, expect
-
-   .. attribute:: current
-
-        The current :class:`~jinja2.lexer.Token`.
-
-.. autoclass:: jinja2.lexer.Token
-    :members: test, test_any
-
-    .. attribute:: lineno
-
-        The line number of the token
-
-    .. attribute:: type
-
-        The type of the token.  This string is interned so you may compare
-        it with arbitrary strings using the `is` operator.
-
-    .. attribute:: value
-
-        The value of the token.
-
-There is also a utility function in the lexer module that can count newline
-characters in strings:
-
-.. autofunction:: jinja2.lexer.count_newlines
-
-AST
-~~~
-
-The AST (Abstract Syntax Tree) is used to represent a template after parsing.
-It's build of nodes that the compiler then converts into executable Python
-code objects.  Extensions that provide custom statements can return nodes to
-execute custom Python code.
-
-The list below describes all nodes that are currently available.  The AST may
-change between Jinja2 versions but will stay backwards compatible.
-
-For more information have a look at the repr of :meth:`jinja2.Environment.parse`.
-
-.. module:: jinja2.nodes
-
-.. jinjanodes::
-
-.. autoexception:: Impossible

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/faq.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/faq.rst b/ambari-common/src/main/python/jinja2/docs/faq.rst
deleted file mode 100644
index 89186b1..0000000
--- a/ambari-common/src/main/python/jinja2/docs/faq.rst
+++ /dev/null
@@ -1,191 +0,0 @@
-Frequently Asked Questions
-==========================
-
-This page answers some of the often asked questions about Jinja.
-
-.. highlight:: html+jinja
-
-Why is it called Jinja?
------------------------
-
-The name Jinja was chosen because it's the name of a Japanese temple and
-temple and template share a similar pronunciation.  It is not named after
-the capital city of Uganda.
-
-How fast is it?
----------------
-
-We really hate benchmarks especially since they don't reflect much.  The
-performance of a template depends on many factors and you would have to
-benchmark different engines in different situations.  The benchmarks from the
-testsuite show that Jinja2 has a similar performance to `Mako`_ and is between
-10 and 20 times faster than Django's template engine or Genshi.  These numbers
-should be taken with tons of salt as the benchmarks that took these numbers
-only test a few performance related situations such as looping.  Generally
-speaking the performance of a template engine doesn't matter much as the
-usual bottleneck in a web application is either the database or the application
-code.
-
-.. _Mako: http://www.makotemplates.org/
-
-How Compatible is Jinja2 with Django?
--------------------------------------
-
-The default syntax of Jinja2 matches Django syntax in many ways.  However
-this similarity doesn't mean that you can use a Django template unmodified
-in Jinja2.  For example filter arguments use a function call syntax rather
-than a colon to separate filter name and arguments.  Additionally the
-extension interface in Jinja is fundamentally different from the Django one
-which means that your custom tags won't work any longer.
-
-Generally speaking you will use much less custom extensions as the Jinja
-template system allows you to use a certain subset of Python expressions
-which can replace most Django extensions.  For example instead of using
-something like this::
-
-    {% load comments %}
-    {% get_latest_comments 10 as latest_comments %}
-    {% for comment in latest_comments %}
-        ...
-    {% endfor %}
-
-You will most likely provide an object with attributes to retrieve
-comments from the database::
-
-    {% for comment in models.comments.latest(10) %}
-        ...
-    {% endfor %}
-
-Or directly provide the model for quick testing::
-
-    {% for comment in Comment.objects.order_by('-pub_date')[:10] %}
-        ...
-    {% endfor %}
-
-Please keep in mind that even though you may put such things into templates
-it still isn't a good idea.  Queries should go into the view code and not
-the template!
-
-Isn't it a terrible idea to put Logic into Templates?
------------------------------------------------------
-
-Without a doubt you should try to remove as much logic from templates as
-possible.  But templates without any logic mean that you have to do all
-the processing in the code which is boring and stupid.  A template engine
-that does that is shipped with Python and called `string.Template`.  Comes
-without loops and if conditions and is by far the fastest template engine
-you can get for Python.
-
-So some amount of logic is required in templates to keep everyone happy.
-And Jinja leaves it pretty much to you how much logic you want to put into
-templates.  There are some restrictions in what you can do and what not.
-
-Jinja2 neither allows you to put arbitrary Python code into templates nor
-does it allow all Python expressions.  The operators are limited to the
-most common ones and more advanced expressions such as list comprehensions
-and generator expressions are not supported.  This keeps the template engine
-easier to maintain and templates more readable.
-
-Why is Autoescaping not the Default?
-------------------------------------
-
-There are multiple reasons why automatic escaping is not the default mode
-and also not the recommended one.  While automatic escaping of variables
-means that you will less likely have an XSS problem it also causes a huge
-amount of extra processing in the template engine which can cause serious
-performance problems.  As Python doesn't provide a way to mark strings as
-unsafe Jinja has to hack around that limitation by providing a custom
-string class (the :class:`Markup` string) that safely interacts with safe
-and unsafe strings.
-
-With explicit escaping however the template engine doesn't have to perform
-any safety checks on variables.  Also a human knows not to escape integers
-or strings that may never contain characters one has to escape or already
-HTML markup.  For example when iterating over a list over a table of
-integers and floats for a table of statistics the template designer can
-omit the escaping because he knows that integers or floats don't contain
-any unsafe parameters.
-
-Additionally Jinja2 is a general purpose template engine and not only used
-for HTML/XML generation.  For example you may generate LaTeX, emails,
-CSS, JavaScript, or configuration files.
-
-Why is the Context immutable?
------------------------------
-
-When writing a :func:`contextfunction` or something similar you may have
-noticed that the context tries to stop you from modifying it.  If you have
-managed to modify the context by using an internal context API you may
-have noticed that changes in the context don't seem to be visible in the
-template.  The reason for this is that Jinja uses the context only as
-primary data source for template variables for performance reasons.
-
-If you want to modify the context write a function that returns a variable
-instead that one can assign to a variable by using set::
-
-    {% set comments = get_latest_comments() %}
-
-What is the speedups module and why is it missing?
---------------------------------------------------
-
-To achieve a good performance with automatic escaping enabled, the escaping
-function was also implemented in pure C in older Jinja2 releases and used if
-Jinja2 was installed with the speedups module.
-
-Because this feature itself is very useful for non-template engines as
-well it was moved into a separate project on PyPI called `MarkupSafe`_.
-
-Jinja2 no longer ships with a C implementation of it but only the pure
-Python implementation.  It will however check if MarkupSafe is available
-and installed, and if it is, use the Markup class from MarkupSafe.
-
-So if you want the speedups, just import MarkupSafe.
-
-.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
-
-My tracebacks look weird.  What's happening?
---------------------------------------------
-
-If the debugsupport module is not compiled and you are using a Python
-installation without ctypes (Python 2.4 without ctypes, Jython or Google's
-AppEngine) Jinja2 is unable to provide correct debugging information and
-the traceback may be incomplete.  There is currently no good workaround
-for Jython or the AppEngine as ctypes is unavailable there and it's not
-possible to use the debugsupport extension.
-
-Why is there no Python 2.3 support?
------------------------------------
-
-Python 2.3 is missing a lot of features that are used heavily in Jinja2.  This
-decision was made as with the upcoming Python 2.6 and 3.0 versions it becomes
-harder to maintain the code for older Python versions.  If you really need
-Python 2.3 support you either have to use `Jinja 1`_ or other templating
-engines that still support 2.3.
-
-My Macros are overriden by something
-------------------------------------
-
-In some situations the Jinja scoping appears arbitrary:
-
-layout.tmpl:
-
-.. sourcecode:: jinja
-
-    {% macro foo() %}LAYOUT{% endmacro %}
-    {% block body %}{% endblock %}
-
-child.tmpl:
-
-.. sourcecode:: jinja
-
-    {% extends 'layout.tmpl' %}
-    {% macro foo() %}CHILD{% endmacro %}
-    {% block body %}{{ foo() }}{% endblock %}
-
-This will print ``LAYOUT`` in Jinja2.  This is a side effect of having
-the parent template evaluated after the child one.  This allows child
-templates passing information to the parent template.  To avoid this
-issue rename the macro or variable in the parent template to have an
-uncommon prefix.
-
-.. _Jinja 1: http://jinja.pocoo.org/1/

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/index.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/index.rst b/ambari-common/src/main/python/jinja2/docs/index.rst
deleted file mode 100644
index 27bee23..0000000
--- a/ambari-common/src/main/python/jinja2/docs/index.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-Jinja2 Documentation
-====================
-
-This is the documentation for the Jinja2 general purpose templating language.
-Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
-fast and secure.
-
-.. toctree::
-   :maxdepth: 2
-
-   intro
-   api
-   sandbox
-   templates
-   extensions
-   integration
-   switching
-   tricks
-
-   faq
-   changelog
-
-If you can't find the information you're looking for, have a look at the
-index of try to find it using the search function:
-
-* :ref:`genindex`
-* :ref:`search`

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/integration.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/integration.rst b/ambari-common/src/main/python/jinja2/docs/integration.rst
deleted file mode 100644
index 1875711..0000000
--- a/ambari-common/src/main/python/jinja2/docs/integration.rst
+++ /dev/null
@@ -1,88 +0,0 @@
-Integration
-===========
-
-Jinja2 provides some code for integration into other tools such as frameworks,
-the `Babel`_ library or your favourite editor for fancy code highlighting.
-This is a brief description of whats included.
-
-.. _babel-integration:
-
-Babel Integration
------------------
-
-Jinja provides support for extracting gettext messages from templates via a
-`Babel`_ extractor entry point called `jinja2.ext.babel_extract`.  The Babel
-support is implemented as part of the :ref:`i18n-extension` extension.
-
-Gettext messages extracted from both `trans` tags and code expressions.
-
-To extract gettext messages from templates, the project needs a Jinja2 section
-in its Babel extraction method `mapping file`_:
-
-.. sourcecode:: ini
-
-    [jinja2: **/templates/**.html]
-    encoding = utf-8
-
-The syntax related options of the :class:`Environment` are also available as
-configuration values in the mapping file.  For example to tell the extraction
-that templates use ``%`` as `line_statement_prefix` you can use this code:
-
-.. sourcecode:: ini
-
-    [jinja2: **/templates/**.html]
-    encoding = utf-8
-    line_statement_prefix = %
-
-:ref:`jinja-extensions` may also be defined by passing a comma separated list
-of import paths as `extensions` value.  The i18n extension is added
-automatically.
-
-.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
-
-Pylons
-------
-
-With `Pylons`_ 0.9.7 onwards it's incredible easy to integrate Jinja into a
-Pylons powered application.
-
-The template engine is configured in `config/environment.py`.  The configuration
-for Jinja2 looks something like that::
-
-    from jinja2 import Environment, PackageLoader
-    config['pylons.app_globals'].jinja_env = Environment(
-        loader=PackageLoader('yourapplication', 'templates')
-    )
-
-After that you can render Jinja templates by using the `render_jinja` function
-from the `pylons.templating` module.
-
-Additionally it's a good idea to set the Pylons' `c` object into strict mode.
-Per default any attribute to not existing attributes on the `c` object return
-an empty string and not an undefined object.  To change this just use this
-snippet and add it into your `config/environment.py`::
-
-    config['pylons.strict_c'] = True
-
-.. _Pylons: http://www.pylonshq.com/
-
-TextMate
---------
-
-Inside the `ext` folder of Jinja2 there is a bundle for TextMate that supports
-syntax highlighting for Jinja1 and Jinja2 for text based templates as well as
-HTML.  It also contains a few often used snippets.
-
-Vim
----
-
-A syntax plugin for `Vim`_ exists in the Vim-scripts directory as well as the
-ext folder of Jinja2.  `The script <http://www.vim.org/scripts/script.php?script_id=1856>`_
-supports Jinja1 and Jinja2.  Once installed two file types are available `jinja`
-and `htmljinja`.  The first one for text based templates, the latter for HTML
-templates.
-
-Copy the files into your `syntax` folder.
-
-.. _Babel: http://babel.edgewall.org/
-.. _Vim: http://www.vim.org/

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/intro.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/intro.rst b/ambari-common/src/main/python/jinja2/docs/intro.rst
deleted file mode 100644
index 0800615..0000000
--- a/ambari-common/src/main/python/jinja2/docs/intro.rst
+++ /dev/null
@@ -1,168 +0,0 @@
-Introduction
-============
-
-This is the documentation for the Jinja2 general purpose templating language.
-Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible,
-fast and secure.
-
-If you have any exposure to other text-based template languages, such as Smarty or
-Django, you should feel right at home with Jinja2.  It's both designer and
-developer friendly by sticking to Python's principles and adding functionality
-useful for templating environments.
-
-The key-features are...
-
--   ... **configurable syntax**.  If you are generating LaTeX or other formats
-    with Jinja2 you can change the delimiters to something that integrates better
-    into the LaTeX markup.
-
--   ... **fast**.  While performance is not the primarily target of Jinja2 it's
-    surprisingly fast.  The overhead compared to regular Python code was reduced
-    to the very minimum.
-
--   ... **easy to debug**.  Jinja2 integrates directly into the python traceback
-    system which allows you to debug Jinja2 templates with regular python
-    debugging helpers.
-
--   ... **secure**.  It's possible to evaluate untrusted template code if the
-    optional sandbox is enabled.  This allows Jinja2 to be used as templating
-    language for applications where users may modify the template design.
-
-
-Prerequisites
--------------
-
-Jinja2 needs at least **Python 2.4** to run.  Additionally a working C-compiler
-that can create python extensions should be installed for the debugger if you
-are using Python 2.4.
-
-If you don't have a working C-compiler and you are trying to install the source
-release with the debugsupport you will get a compiler error.
-
-.. _ctypes: http://python.net/crew/theller/ctypes/
-
-
-Installation
-------------
-
-You have multiple ways to install Jinja2.  If you are unsure what to do, go
-with the Python egg or tarball.
-
-As a Python egg (via easy_install)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can install the most recent Jinja2 version using `easy_install`_ or `pip`_::
-
-    easy_install Jinja2
-    pip install Jinja2
-
-This will install a Jinja2 egg in your Python installation's site-packages
-directory.
-
-(If you are installing from the windows command line omit the `sudo` and make
-sure to run the command as user with administrator rights)
-
-From the tarball release
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1.  Download the most recent tarball from the `download page`_
-2.  Unpack the tarball
-3.  ``sudo python setup.py install``
-
-Note that you either have to have setuptools or `distribute`_ installed,
-the latter is preferred.
-
-This will install Jinja2 into your Python installation's site-packages directory.
-
-.. _distribute: http://pypi.python.org/pypi/distribute
-
-Installing the development version
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1.  Install `git`_
-2.  ``git clone git://github.com/mitsuhiko/jinja2.git``
-3.  ``cd jinja2``
-4.  ``ln -s jinja2 /usr/lib/python2.X/site-packages``
-
-As an alternative to steps 4 you can also do ``python setup.py develop``
-which will install the package via distribute in development mode.  This also
-has the advantage that the C extensions are compiled.
-
-.. _download page: http://pypi.python.org/pypi/Jinja2
-.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
-.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
-.. _pip: http://pypi.python.org/pypi/pip
-.. _git: http://git-scm.org/
-
-
-More Speed with MarkupSafe
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-As of version 2.5.1 Jinja2 will check for an installed `MarkupSafe`_
-module.  If it can find it, it will use the Markup class of that module
-instead of the one that comes with Jinja2.  `MarkupSafe` replaces the
-older speedups module that came with Jinja2 and has the advantage that is
-has a better setup script and will automatically attempt to install the C
-version and nicely fall back to a pure Python implementation if that is
-not possible.
-
-The C implementation of MarkupSafe is much faster and recommended when
-using Jinja2 with autoescaping.
-
-.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
-
-
-Enable the debug support Module
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-By default Jinja2 will not compile the debug support module.  Enabling this
-will fail if you don't have the Python headers or a working compiler.  This
-is often the case if you are installing Jinja2 from a windows machine.
-
-Because the debug support is only necessary for Python 2.4 you will not
-have to do this unless you run 2.4::
-
-    sudo python setup.py --with-debugsupport install
-
-
-Basic API Usage
----------------
-
-This section gives you a brief introduction to the Python API for Jinja2
-templates.
-
-The most basic way to create a template and render it is through
-:class:`~jinja2.Template`.  This however is not the recommended way to
-work with it if your templates are not loaded from strings but the file
-system or another data source:
-
->>> from jinja2 import Template
->>> template = Template('Hello {{ name }}!')
->>> template.render(name='John Doe')
-u'Hello John Doe!'
-
-By creating an instance of :class:`~jinja2.Template` you get back a new template
-object that provides a method called :meth:`~jinja2.Template.render` which when
-called with a dict or keyword arguments expands the template.  The dict
-or keywords arguments passed to the template are the so-called "context"
-of the template.
-
-What you can see here is that Jinja2 is using unicode internally and the
-return value is an unicode string.  So make sure that your application is
-indeed using unicode internally.
-
-
-Experimental Python 3 Support
------------------------------
-
-Jinja 2.3 brings experimental support for Python 3.  It means that all
-unittests pass on the new version, but there might still be small bugs in
-there and behavior might be inconsistent.  If you notice any bugs, please
-provide feedback in the `Jinja bug tracker`_.
-
-Also please keep in mind that the documentation is written with Python 2
-in mind, you will have to adapt the shown code examples to Python 3 syntax
-for yourself.
-
-
-.. _Jinja bug tracker: http://github.com/mitsuhiko/jinja2/issues

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/jinjaext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/jinjaext.py b/ambari-common/src/main/python/jinja2/docs/jinjaext.py
deleted file mode 100644
index 66f4ba1..0000000
--- a/ambari-common/src/main/python/jinja2/docs/jinjaext.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    Jinja Documentation Extensions
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Support for automatically documenting filters and tests.
-
-    :copyright: Copyright 2008 by Armin Ronacher.
-    :license: BSD.
-"""
-import os
-import re
-import inspect
-import jinja2
-from itertools import islice
-from types import BuiltinFunctionType
-from docutils import nodes
-from docutils.statemachine import ViewList
-from sphinx.ext.autodoc import prepare_docstring
-from sphinx.application import TemplateBridge
-from pygments.style import Style
-from pygments.token import Keyword, Name, Comment, String, Error, \
-     Number, Operator, Generic
-from jinja2 import Environment, FileSystemLoader
-
-
-def parse_rst(state, content_offset, doc):
-    node = nodes.section()
-    # hack around title style bookkeeping
-    surrounding_title_styles = state.memo.title_styles
-    surrounding_section_level = state.memo.section_level
-    state.memo.title_styles = []
-    state.memo.section_level = 0
-    state.nested_parse(doc, content_offset, node, match_titles=1)
-    state.memo.title_styles = surrounding_title_styles
-    state.memo.section_level = surrounding_section_level
-    return node.children
-
-
-class JinjaStyle(Style):
-    title = 'Jinja Style'
-    default_style = ""
-    styles = {
-        Comment:                    'italic #aaaaaa',
-        Comment.Preproc:            'noitalic #B11414',
-        Comment.Special:            'italic #505050',
-
-        Keyword:                    'bold #B80000',
-        Keyword.Type:               '#808080',
-
-        Operator.Word:              'bold #B80000',
-
-        Name.Builtin:               '#333333',
-        Name.Function:              '#333333',
-        Name.Class:                 'bold #333333',
-        Name.Namespace:             'bold #333333',
-        Name.Entity:                'bold #363636',
-        Name.Attribute:             '#686868',
-        Name.Tag:                   'bold #686868',
-        Name.Decorator:             '#686868',
-
-        String:                     '#AA891C',
-        Number:                     '#444444',
-
-        Generic.Heading:            'bold #000080',
-        Generic.Subheading:         'bold #800080',
-        Generic.Deleted:            '#aa0000',
-        Generic.Inserted:           '#00aa00',
-        Generic.Error:              '#aa0000',
-        Generic.Emph:               'italic',
-        Generic.Strong:             'bold',
-        Generic.Prompt:             '#555555',
-        Generic.Output:             '#888888',
-        Generic.Traceback:          '#aa0000',
-
-        Error:                      '#F00 bg:#FAA'
-    }
-
-
-_sig_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))')
-
-
-def format_function(name, aliases, func):
-    lines = inspect.getdoc(func).splitlines()
-    signature = '()'
-    if isinstance(func, BuiltinFunctionType):
-        match = _sig_re.match(lines[0])
-        if match is not None:
-            del lines[:1 + bool(lines and not lines[0])]
-            signature = match.group(1)
-    else:
-        try:
-            argspec = inspect.getargspec(func)
-            if getattr(func, 'environmentfilter', False) or \
-               getattr(func, 'contextfilter', False):
-                del argspec[0][0]
-            signature = inspect.formatargspec(*argspec)
-        except:
-            pass
-    result = ['.. function:: %s%s' % (name, signature), '']
-    result.extend('    ' + line for line in lines)
-    if aliases:
-        result.extend(('', '    :aliases: %s' % ', '.join(
-                      '``%s``' % x for x in sorted(aliases))))
-    return result
-
-
-def dump_functions(mapping):
-    def directive(dirname, arguments, options, content, lineno,
-                      content_offset, block_text, state, state_machine):
-        reverse_mapping = {}
-        for name, func in mapping.iteritems():
-            reverse_mapping.setdefault(func, []).append(name)
-        filters = []
-        for func, names in reverse_mapping.iteritems():
-            aliases = sorted(names, key=lambda x: len(x))
-            name = aliases.pop()
-            filters.append((name, aliases, func))
-        filters.sort()
-
-        result = ViewList()
-        for name, aliases, func in filters:
-            for item in format_function(name, aliases, func):
-                result.append(item, '<jinjaext>')
-
-        node = nodes.paragraph()
-        state.nested_parse(result, content_offset, node)
-        return node.children
-    return directive
-
-
-from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS
-jinja_filters = dump_functions(DEFAULT_FILTERS)
-jinja_tests = dump_functions(DEFAULT_TESTS)
-
-
-def jinja_nodes(dirname, arguments, options, content, lineno,
-                content_offset, block_text, state, state_machine):
-    from jinja2.nodes import Node
-    doc = ViewList()
-    def walk(node, indent):
-        p = ' ' * indent
-        sig = ', '.join(node.fields)
-        doc.append(p + '.. autoclass:: %s(%s)' % (node.__name__, sig), '')
-        if node.abstract:
-            members = []
-            for key, name in node.__dict__.iteritems():
-                if not key.startswith('_') and \
-                   not hasattr(node.__base__, key) and callable(name):
-                    members.append(key)
-            if members:
-                members.sort()
-                doc.append('%s :members: %s' % (p, ', '.join(members)), '')
-        if node.__base__ != object:
-            doc.append('', '')
-            doc.append('%s :Node type: :class:`%s`' %
-                       (p, node.__base__.__name__), '')
-        doc.append('', '')
-        children = node.__subclasses__()
-        children.sort(key=lambda x: x.__name__.lower())
-        for child in children:
-            walk(child, indent)
-    walk(Node, 0)
-    return parse_rst(state, content_offset, doc)
-
-
-def inject_toc(app, doctree, docname):
-    titleiter = iter(doctree.traverse(nodes.title))
-    try:
-        # skip first title, we are not interested in that one
-        titleiter.next()
-        title = titleiter.next()
-        # and check if there is at least another title
-        titleiter.next()
-    except StopIteration:
-        return
-    tocnode = nodes.section('')
-    tocnode['classes'].append('toc')
-    toctitle = nodes.section('')
-    toctitle['classes'].append('toctitle')
-    toctitle.append(nodes.title(text='Table Of Contents'))
-    tocnode.append(toctitle)
-    tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1]
-    title.parent.insert(title.parent.children.index(title), tocnode)
-
-
-def setup(app):
-    app.add_directive('jinjafilters', jinja_filters, 0, (0, 0, 0))
-    app.add_directive('jinjatests', jinja_tests, 0, (0, 0, 0))
-    app.add_directive('jinjanodes', jinja_nodes, 0, (0, 0, 0))
-    # uncomment for inline toc.  links are broken unfortunately
-    ##app.connect('doctree-resolved', inject_toc)

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/sandbox.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/sandbox.rst b/ambari-common/src/main/python/jinja2/docs/sandbox.rst
deleted file mode 100644
index bb0ca9f..0000000
--- a/ambari-common/src/main/python/jinja2/docs/sandbox.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-Sandbox
-=======
-
-The Jinja2 sandbox can be used to evaluate untrusted code.  Access to unsafe
-attributes and methods is prohibited.
-
-Assuming `env` is a :class:`SandboxedEnvironment` in the default configuration
-the following piece of code shows how it works:
-
->>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
-u''
->>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
-Traceback (most recent call last):
-  ...
-SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
-
-
-.. module:: jinja2.sandbox
-
-.. autoclass:: SandboxedEnvironment([options])
-    :members: is_safe_attribute, is_safe_callable
-
-.. autoclass:: ImmutableSandboxedEnvironment([options])
-
-.. autoexception:: SecurityError
-
-.. autofunction:: unsafe
-
-.. autofunction:: is_internal_attribute
-
-.. autofunction:: modifies_known_mutable
-
-.. admonition:: Note
-
-    The Jinja2 sandbox alone is no solution for perfect security.  Especially
-    for web applications you have to keep in mind that users may create
-    templates with arbitrary HTML in so it's crucial to ensure that (if you
-    are running multiple users on the same server) they can't harm each other
-    via JavaScript insertions and much more.
-
-    Also the sandbox is only as good as the configuration.  We stronly
-    recommend only passing non-shared resources to the template and use
-    some sort of whitelisting for attributes.
-
-    Also keep in mind that templates may raise runtime or compile time errors,
-    so make sure to catch them.

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/jinja2/docs/switching.rst
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/jinja2/docs/switching.rst b/ambari-common/src/main/python/jinja2/docs/switching.rst
deleted file mode 100644
index ba3cfb1..0000000
--- a/ambari-common/src/main/python/jinja2/docs/switching.rst
+++ /dev/null
@@ -1,242 +0,0 @@
-Switching from other Template Engines
-=====================================
-
-.. highlight:: html+jinja
-
-If you have used a different template engine in the past and want to swtich
-to Jinja2 here is a small guide that shows the basic syntatic and semantic
-changes between some common, similar text template engines for Python.
-
-Jinja1
-------
-
-Jinja2 is mostly compatible with Jinja1 in terms of API usage and template
-syntax.  The differences between Jinja1 and 2 are explained in the following
-list.
-
-API
-~~~
-
-Loaders
-    Jinja2 uses a different loader API.  Because the internal representation
-    of templates changed there is no longer support for external caching
-    systems such as memcached.  The memory consumed by templates is comparable
-    with regular Python modules now and external caching doesn't give any
-    advantage.  If you have used a custom loader in the past have a look at
-    the new :ref:`loader API <loaders>`.
-
-Loading templates from strings
-    In the past it was possible to generate templates from a string with the
-    default environment configuration by using `jinja.from_string`.  Jinja2
-    provides a :class:`Template` class that can be used to do the same, but
-    with optional additional configuration.
-
-Automatic unicode conversion
-    Jinja1 performed automatic conversion of bytestrings in a given encoding
-    into unicode objects.  This conversion is no longer implemented as it
-    was inconsistent as most libraries are using the regular Python ASCII
-    bytestring to Unicode conversion.  An application powered by Jinja2
-    *has to* use unicode internally everywhere or make sure that Jinja2 only
-    gets unicode strings passed.
-
-i18n
-    Jinja1 used custom translators for internationalization.  i18n is now
-    available as Jinja2 extension and uses a simpler, more gettext friendly
-    interface and has support for babel.  For more details see
-    :ref:`i18n-extension`.
-
-Internal methods
-    Jinja1 exposed a few internal methods on the environment object such
-    as `call_function`, `get_attribute` and others.  While they were marked
-    as being an internal method it was possible to override them.  Jinja2
-    doesn't have equivalent methods.
-
-Sandbox
-    Jinja1 was running sandbox mode by default.  Few applications actually
-    used that feature so it became optional in Jinja2.  For more details
-    about the sandboxed execution see :class:`SandboxedEnvironment`.
-
-Context
-    Jinja1 had a stacked context as storage for variables passed to the
-    environment.  In Jinja2 a similar object exists but it doesn't allow
-    modifications nor is it a singleton.  As inheritance is dynamic now
-    multiple context objects may exist during template evaluation.
-
-Filters and Tests
-    Filters and tests are regular functions now.  It's no longer necessary
-    and allowed to use factory functions.
-
-
-Templates
-~~~~~~~~~
-
-Jinja2 has mostly the same syntax as Jinja1.  What's different is that
-macros require parentheses around the argument list now.
-
-Additionally Jinja2 allows dynamic inheritance now and dynamic includes.
-The old helper function `rendertemplate` is gone now, `include` can be used
-instead.  Includes no longer import macros and variable assignments, for
-that the new `import` tag is used.  This concept is explained in the
-:ref:`import` documentation.
-
-Another small change happened in the `for`-tag.  The special loop variable
-doesn't have a `parent` attribute, instead you have to alias the loop
-yourself.  See :ref:`accessing-the-parent-loop` for more details.
-
-
-Django
-------
-
-If you have previously worked with Django templates, you should find
-Jinja2 very familiar.  In fact, most of the syntax elements look and
-work the same.
-
-However, Jinja2 provides some more syntax elements covered in the
-documentation and some work a bit different.
-
-This section covers the template changes.  As the API is fundamentally
-different we won't cover it here.
-
-Method Calls
-~~~~~~~~~~~~
-
-In Django method calls work implicitly.  With Jinja2 you have to specify that
-you want to call an object.  Thus this Django code::
-
-    {% for page in user.get_created_pages %}
-        ...
-    {% endfor %}
-    
-will look like this in Jinja::
-
-    {% for page in user.get_created_pages() %}
-        ...
-    {% endfor %}
-
-This allows you to pass variables to the function which is also used for macros
-which is not possible in Django.
-
-Conditions
-~~~~~~~~~~
-
-In Django you can use the following constructs to check for equality::
-
-    {% ifequal foo "bar" %}
-        ...
-    {% else %}
-        ...
-    {% endifequal %}
-
-In Jinja2 you can use the normal if statement in combination with operators::
-
-    {% if foo == 'bar' %}
-        ...
-    {% else %}
-        ...
-    {% endif %}
-
-You can also have multiple elif branches in your template::
-
-    {% if something %}
-        ...
-    {% elif otherthing %}
-        ...
-    {% elif foothing %}
-        ...
-    {% else %}
-        ...
-    {% endif %}
-
-Filter Arguments
-~~~~~~~~~~~~~~~~
-
-Jinja2 provides more than one argument for filters.  Also the syntax for
-argument passing is different.  A template that looks like this in Django::
-
-    {{ items|join:", " }}
-
-looks like this in Jinja2::
-
-    {{ items|join(', ') }}
-
-In fact it's a bit more verbose but it allows different types of arguments -
-including variables - and more than one of them.
-
-Tests
-~~~~~
-
-In addition to filters there also are tests you can perform using the is
-operator.  Here are some examples::
-
-    {% if user.user_id is odd %}
-        {{ user.username|e }} is odd
-    {% else %}
-        hmm. {{ user.username|e }} looks pretty normal
-    {% endif %}
-
-Loops
-~~~~~
-
-For loops work very similar to Django, the only incompatibility is that in
-Jinja2 the special variable for the loop context is called `loop` and not
-`forloop` like in Django.
-
-Cycle
-~~~~~
-
-The ``{% cycle %}`` tag does not exist in Jinja because of it's implicit
-nature.  However you can achieve mostly the same by using the `cycle`
-method on a loop object.
-
-The following Django template::
-
-    {% for user in users %}
-        <li class="{% cycle 'odd' 'even' %}">{{ user }}</li>
-    {% endfor %}
-
-Would look like this in Jinja::
-
-    {% for user in users %}
-        <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
-    {% endfor %}
-
-There is no equivalent of ``{% cycle ... as variable %}``.
-
-
-Mako
-----
-
-.. highlight:: html+mako
-
-If you have used Mako so far and want to switch to Jinja2 you can configure
-Jinja2 to look more like Mako:
-
-.. sourcecode:: python
-
-    env = Environment('<%', '%>', '${', '}', '%')
-
-Once the environment is configure like that Jinja2 should be able to interpret
-a small subset of Mako templates.  Jinja2 does not support embedded Python code
-so you would have to move that out of the template.  The syntax for defs (in
-Jinja2 defs are called macros) and template inheritance is different too.  The
-following Mako template::
-
-    <%inherit file="layout.html" />
-    <%def name="title()">Page Title</%def>
-    <ul>
-    % for item in list:
-        <li>${item}</li>
-    % endfor
-    </ul>
-
-Looks like this in Jinja2 with the above configuration::
-
-    <% extends "layout.html" %>
-    <% block title %>Page Title<% endblock %>
-    <% block body %>
-    <ul>
-    % for item in list:
-        <li>${item}</li>
-    % endfor
-    </ul>
-    <% endblock %>


[48/59] [abbrv] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

Posted by nc...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py
new file mode 100644
index 0000000..b3d6bc7
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/environment.py
@@ -0,0 +1,1118 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.environment
+    ~~~~~~~~~~~~~~~~~~
+
+    Provides a class that holds runtime and parsing time options.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+from ambari_jinja2 import nodes
+from ambari_jinja2.defaults import *
+from ambari_jinja2.lexer import get_lexer, TokenStream
+from ambari_jinja2.parser import Parser
+from ambari_jinja2.optimizer import optimize
+from ambari_jinja2.compiler import generate
+from ambari_jinja2.runtime import Undefined, new_context
+from ambari_jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
+     TemplatesNotFound
+from ambari_jinja2.utils import import_string, LRUCache, Markup, missing, \
+     concat, consume, internalcode, _encode_filename
+
+
+# for direct template usage we have up to ten living environments
+_spontaneous_environments = LRUCache(10)
+
+# the function to create jinja traceback objects.  This is dynamically
+# imported on the first exception in the exception handler.
+_make_traceback = None
+
+
+def get_spontaneous_environment(*args):
+    """Return a new spontaneous environment.  A spontaneous environment is an
+    unnamed and unaccessible (in theory) environment that is used for
+    templates generated from a string and not from the file system.
+    """
+    try:
+        env = _spontaneous_environments.get(args)
+    except TypeError:
+        return Environment(*args)
+    if env is not None:
+        return env
+    _spontaneous_environments[args] = env = Environment(*args)
+    env.shared = True
+    return env
+
+
+def create_cache(size):
+    """Return the cache class for the given size."""
+    if size == 0:
+        return None
+    if size < 0:
+        return {}
+    return LRUCache(size)
+
+
+def copy_cache(cache):
+    """Create an empty copy of the given cache."""
+    if cache is None:
+        return None
+    elif type(cache) is dict:
+        return {}
+    return LRUCache(cache.capacity)
+
+
+def load_extensions(environment, extensions):
+    """Load the extensions from the list and bind it to the environment.
+    Returns a dict of instanciated environments.
+    """
+    result = {}
+    for extension in extensions:
+        if isinstance(extension, basestring):
+            extension = import_string(extension)
+        result[extension.identifier] = extension(environment)
+    return result
+
+
+def _environment_sanity_check(environment):
+    """Perform a sanity check on the environment."""
+    assert issubclass(environment.undefined, Undefined), 'undefined must ' \
+           'be a subclass of undefined because filters depend on it.'
+    assert environment.block_start_string != \
+           environment.variable_start_string != \
+           environment.comment_start_string, 'block, variable and comment ' \
+           'start strings must be different'
+    assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
+           'newline_sequence set to unknown line ending string.'
+    return environment
+
+
+class Environment(object):
+    r"""The core component of Jinja is the `Environment`.  It contains
+    important shared variables like configuration, filters, tests,
+    globals and others.  Instances of this class may be modified if
+    they are not shared and if no template was loaded so far.
+    Modifications on environments after the first template was loaded
+    will lead to surprising effects and undefined behavior.
+
+    Here the possible initialization parameters:
+
+        `block_start_string`
+            The string marking the begin of a block.  Defaults to ``'{%'``.
+
+        `block_end_string`
+            The string marking the end of a block.  Defaults to ``'%}'``.
+
+        `variable_start_string`
+            The string marking the begin of a print statement.
+            Defaults to ``'{{'``.
+
+        `variable_end_string`
+            The string marking the end of a print statement.  Defaults to
+            ``'}}'``.
+
+        `comment_start_string`
+            The string marking the begin of a comment.  Defaults to ``'{#'``.
+
+        `comment_end_string`
+            The string marking the end of a comment.  Defaults to ``'#}'``.
+
+        `line_statement_prefix`
+            If given and a string, this will be used as prefix for line based
+            statements.  See also :ref:`line-statements`.
+
+        `line_comment_prefix`
+            If given and a string, this will be used as prefix for line based
+            based comments.  See also :ref:`line-statements`.
+
+            .. versionadded:: 2.2
+
+        `trim_blocks`
+            If this is set to ``True`` the first newline after a block is
+            removed (block, not variable tag!).  Defaults to `False`.
+
+        `newline_sequence`
+            The sequence that starts a newline.  Must be one of ``'\r'``,
+            ``'\n'`` or ``'\r\n'``.  The default is ``'\n'`` which is a
+            useful default for Linux and OS X systems as well as web
+            applications.
+
+        `extensions`
+            List of Jinja extensions to use.  This can either be import paths
+            as strings or extension classes.  For more information have a
+            look at :ref:`the extensions documentation <jinja-extensions>`.
+
+        `optimized`
+            should the optimizer be enabled?  Default is `True`.
+
+        `undefined`
+            :class:`Undefined` or a subclass of it that is used to represent
+            undefined values in the template.
+
+        `finalize`
+            A callable that can be used to process the result of a variable
+            expression before it is output.  For example one can convert
+            `None` implicitly into an empty string here.
+
+        `autoescape`
+            If set to true the XML/HTML autoescaping feature is enabled by
+            default.  For more details about auto escaping see
+            :class:`~ambari_jinja2.utils.Markup`.  As of Jinja 2.4 this can also
+            be a callable that is passed the template name and has to
+            return `True` or `False` depending on autoescape should be
+            enabled by default.
+
+            .. versionchanged:: 2.4
+               `autoescape` can now be a function
+
+        `loader`
+            The template loader for this environment.
+
+        `cache_size`
+            The size of the cache.  Per default this is ``50`` which means
+            that if more than 50 templates are loaded the loader will clean
+            out the least recently used template.  If the cache size is set to
+            ``0`` templates are recompiled all the time, if the cache size is
+            ``-1`` the cache will not be cleaned.
+
+        `auto_reload`
+            Some loaders load templates from locations where the template
+            sources may change (ie: file system or database).  If
+            `auto_reload` is set to `True` (default) every time a template is
+            requested the loader checks if the source changed and if yes, it
+            will reload the template.  For higher performance it's possible to
+            disable that.
+
+        `bytecode_cache`
+            If set to a bytecode cache object, this object will provide a
+            cache for the internal Jinja bytecode so that templates don't
+            have to be parsed if they were not changed.
+
+            See :ref:`bytecode-cache` for more information.
+    """
+
+    #: if this environment is sandboxed.  Modifying this variable won't make
+    #: the environment sandboxed though.  For a real sandboxed environment
+    #: have a look at ambari_jinja2.sandbox
+    sandboxed = False
+
+    #: True if the environment is just an overlay
+    overlayed = False
+
+    #: the environment this environment is linked to if it is an overlay
+    linked_to = None
+
+    #: shared environments have this set to `True`.  A shared environment
+    #: must not be modified
+    shared = False
+
+    #: these are currently EXPERIMENTAL undocumented features.
+    exception_handler = None
+    exception_formatter = None
+
+    def __init__(self,
+                 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,
+                 line_statement_prefix=LINE_STATEMENT_PREFIX,
+                 line_comment_prefix=LINE_COMMENT_PREFIX,
+                 trim_blocks=TRIM_BLOCKS,
+                 newline_sequence=NEWLINE_SEQUENCE,
+                 extensions=(),
+                 optimized=True,
+                 undefined=Undefined,
+                 finalize=None,
+                 autoescape=False,
+                 loader=None,
+                 cache_size=50,
+                 auto_reload=True,
+                 bytecode_cache=None):
+        # !!Important notice!!
+        #   The constructor accepts quite a few arguments that should be
+        #   passed by keyword rather than position.  However it's important to
+        #   not change the order of arguments because it's used at least
+        #   internally in those cases:
+        #       -   spontaneus environments (i18n extension and Template)
+        #       -   unittests
+        #   If parameter changes are required only add parameters at the end
+        #   and don't change the arguments (or the defaults!) of the arguments
+        #   existing already.
+
+        # lexer / parser information
+        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.line_statement_prefix = line_statement_prefix
+        self.line_comment_prefix = line_comment_prefix
+        self.trim_blocks = trim_blocks
+        self.newline_sequence = newline_sequence
+
+        # runtime information
+        self.undefined = undefined
+        self.optimized = optimized
+        self.finalize = finalize
+        self.autoescape = autoescape
+
+        # defaults
+        self.filters = DEFAULT_FILTERS.copy()
+        self.tests = DEFAULT_TESTS.copy()
+        self.globals = DEFAULT_NAMESPACE.copy()
+
+        # set the loader provided
+        self.loader = loader
+        self.bytecode_cache = None
+        self.cache = create_cache(cache_size)
+        self.bytecode_cache = bytecode_cache
+        self.auto_reload = auto_reload
+
+        # load extensions
+        self.extensions = load_extensions(self, extensions)
+
+        _environment_sanity_check(self)
+
+    def add_extension(self, extension):
+        """Adds an extension after the environment was created.
+
+        .. versionadded:: 2.5
+        """
+        self.extensions.update(load_extensions(self, [extension]))
+
+    def extend(self, **attributes):
+        """Add the items to the instance of the environment if they do not exist
+        yet.  This is used by :ref:`extensions <writing-extensions>` to register
+        callbacks and configuration values without breaking inheritance.
+        """
+        for key, value in attributes.iteritems():
+            if not hasattr(self, key):
+                setattr(self, key, value)
+
+    def overlay(self, block_start_string=missing, block_end_string=missing,
+                variable_start_string=missing, variable_end_string=missing,
+                comment_start_string=missing, comment_end_string=missing,
+                line_statement_prefix=missing, line_comment_prefix=missing,
+                trim_blocks=missing, extensions=missing, optimized=missing,
+                undefined=missing, finalize=missing, autoescape=missing,
+                loader=missing, cache_size=missing, auto_reload=missing,
+                bytecode_cache=missing):
+        """Create a new overlay environment that shares all the data with the
+        current environment except of cache and the overridden attributes.
+        Extensions cannot be removed for an overlayed environment.  An overlayed
+        environment automatically gets all the extensions of the environment it
+        is linked to plus optional extra extensions.
+
+        Creating overlays should happen after the initial environment was set
+        up completely.  Not all attributes are truly linked, some are just
+        copied over so modifications on the original environment may not shine
+        through.
+        """
+        args = dict(locals())
+        del args['self'], args['cache_size'], args['extensions']
+
+        rv = object.__new__(self.__class__)
+        rv.__dict__.update(self.__dict__)
+        rv.overlayed = True
+        rv.linked_to = self
+
+        for key, value in args.iteritems():
+            if value is not missing:
+                setattr(rv, key, value)
+
+        if cache_size is not missing:
+            rv.cache = create_cache(cache_size)
+        else:
+            rv.cache = copy_cache(self.cache)
+
+        rv.extensions = {}
+        for key, value in self.extensions.iteritems():
+            rv.extensions[key] = value.bind(rv)
+        if extensions is not missing:
+            rv.extensions.update(load_extensions(rv, extensions))
+
+        return _environment_sanity_check(rv)
+
+    lexer = property(get_lexer, doc="The lexer for this environment.")
+
+    def iter_extensions(self):
+        """Iterates over the extensions by priority."""
+        return iter(sorted(self.extensions.values(),
+                           key=lambda x: x.priority))
+
+    def getitem(self, obj, argument):
+        """Get an item or attribute of an object but prefer the item."""
+        try:
+            return obj[argument]
+        except (TypeError, LookupError):
+            if isinstance(argument, basestring):
+                try:
+                    attr = str(argument)
+                except:
+                    pass
+                else:
+                    try:
+                        return getattr(obj, attr)
+                    except AttributeError:
+                        pass
+            return self.undefined(obj=obj, name=argument)
+
+    def getattr(self, obj, attribute):
+        """Get an item or attribute of an object but prefer the attribute.
+        Unlike :meth:`getitem` the attribute *must* be a bytestring.
+        """
+        try:
+            return getattr(obj, attribute)
+        except AttributeError:
+            pass
+        try:
+            return obj[attribute]
+        except (TypeError, LookupError, AttributeError):
+            return self.undefined(obj=obj, name=attribute)
+
+    @internalcode
+    def parse(self, source, name=None, filename=None):
+        """Parse the sourcecode and return the abstract syntax tree.  This
+        tree of nodes is used by the compiler to convert the template into
+        executable source- or bytecode.  This is useful for debugging or to
+        extract information from templates.
+
+        If you are :ref:`developing Jinja2 extensions <writing-extensions>`
+        this gives you a good overview of the node tree generated.
+        """
+        try:
+            return self._parse(source, name, filename)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
+
+    def _parse(self, source, name, filename):
+        """Internal parsing function used by `parse` and `compile`."""
+        return Parser(self, source, name, _encode_filename(filename)).parse()
+
+    def lex(self, source, name=None, filename=None):
+        """Lex the given sourcecode and return a generator that yields
+        tokens as tuples in the form ``(lineno, token_type, value)``.
+        This can be useful for :ref:`extension development <writing-extensions>`
+        and debugging templates.
+
+        This does not perform preprocessing.  If you want the preprocessing
+        of the extensions to be applied you have to filter source through
+        the :meth:`preprocess` method.
+        """
+        source = unicode(source)
+        try:
+            return self.lexer.tokeniter(source, name, filename)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
+
+    def preprocess(self, source, name=None, filename=None):
+        """Preprocesses the source with all extensions.  This is automatically
+        called for all parsing and compiling methods but *not* for :meth:`lex`
+        because there you usually only want the actual source tokenized.
+        """
+        return reduce(lambda s, e: e.preprocess(s, name, filename),
+                      self.iter_extensions(), unicode(source))
+
+    def _tokenize(self, source, name, filename=None, state=None):
+        """Called by the parser to do the preprocessing and filtering
+        for all the extensions.  Returns a :class:`~ambari_jinja2.lexer.TokenStream`.
+        """
+        source = self.preprocess(source, name, filename)
+        stream = self.lexer.tokenize(source, name, filename, state)
+        for ext in self.iter_extensions():
+            stream = ext.filter_stream(stream)
+            if not isinstance(stream, TokenStream):
+                stream = TokenStream(stream, name, filename)
+        return stream
+
+    def _generate(self, source, name, filename, defer_init=False):
+        """Internal hook that can be overriden to hook a different generate
+        method in.
+
+        .. versionadded:: 2.5
+        """
+        return generate(source, self, name, filename, defer_init=defer_init)
+
+    def _compile(self, source, filename):
+        """Internal hook that can be overriden to hook a different compile
+        method in.
+
+        .. versionadded:: 2.5
+        """
+        return compile(source, filename, 'exec')
+
+    @internalcode
+    def compile(self, source, name=None, filename=None, raw=False,
+                defer_init=False):
+        """Compile a node or template source code.  The `name` parameter is
+        the load name of the template after it was joined using
+        :meth:`join_path` if necessary, not the filename on the file system.
+        the `filename` parameter is the estimated filename of the template on
+        the file system.  If the template came from a database or memory this
+        can be omitted.
+
+        The return value of this method is a python code object.  If the `raw`
+        parameter is `True` the return value will be a string with python
+        code equivalent to the bytecode returned otherwise.  This method is
+        mainly used internally.
+
+        `defer_init` is use internally to aid the module code generator.  This
+        causes the generated code to be able to import without the global
+        environment variable to be set.
+
+        .. versionadded:: 2.4
+           `defer_init` parameter added.
+        """
+        source_hint = None
+        try:
+            if isinstance(source, basestring):
+                source_hint = source
+                source = self._parse(source, name, filename)
+            if self.optimized:
+                source = optimize(source, self)
+            source = self._generate(source, name, filename,
+                                    defer_init=defer_init)
+            if raw:
+                return source
+            if filename is None:
+                filename = '<template>'
+            else:
+                filename = _encode_filename(filename)
+            return self._compile(source, filename)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
+
+    def compile_expression(self, source, undefined_to_none=True):
+        """A handy helper method that returns a callable that accepts keyword
+        arguments that appear as variables in the expression.  If called it
+        returns the result of the expression.
+
+        This is useful if applications want to use the same rules as Jinja
+        in template "configuration files" or similar situations.
+
+        Example usage:
+
+        >>> env = Environment()
+        >>> expr = env.compile_expression('foo == 42')
+        >>> expr(foo=23)
+        False
+        >>> expr(foo=42)
+        True
+
+        Per default the return value is converted to `None` if the
+        expression returns an undefined value.  This can be changed
+        by setting `undefined_to_none` to `False`.
+
+        >>> env.compile_expression('var')() is None
+        True
+        >>> env.compile_expression('var', undefined_to_none=False)()
+        Undefined
+
+        .. versionadded:: 2.1
+        """
+        parser = Parser(self, source, state='variable')
+        exc_info = None
+        try:
+            expr = parser.parse_expression()
+            if not parser.stream.eos:
+                raise TemplateSyntaxError('chunk after expression',
+                                          parser.stream.current.lineno,
+                                          None, None)
+            expr.set_environment(self)
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        if exc_info is not None:
+            self.handle_exception(exc_info, source_hint=source)
+        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
+        template = self.from_string(nodes.Template(body, lineno=1))
+        return TemplateExpression(template, undefined_to_none)
+
+    def compile_templates(self, target, extensions=None, filter_func=None,
+                          zip='deflated', log_function=None,
+                          ignore_errors=True, py_compile=False):
+        """Compiles all the templates the loader can find, compiles them
+        and stores them in `target`.  If `zip` is `None`, instead of in a
+        zipfile, the templates will be will be stored in a directory.
+        By default a deflate zip algorithm is used, to switch to
+        the stored algorithm, `zip` can be set to ``'stored'``.
+
+        `extensions` and `filter_func` are passed to :meth:`list_templates`.
+        Each template returned will be compiled to the target folder or
+        zipfile.
+
+        By default template compilation errors are ignored.  In case a
+        log function is provided, errors are logged.  If you want template
+        syntax errors to abort the compilation you can set `ignore_errors`
+        to `False` and you will get an exception on syntax errors.
+
+        If `py_compile` is set to `True` .pyc files will be written to the
+        target instead of standard .py files.
+
+        .. versionadded:: 2.4
+        """
+        from ambari_jinja2.loaders import ModuleLoader
+
+        if log_function is None:
+            log_function = lambda x: None
+
+        if py_compile:
+            import imp, struct, marshal
+            py_header = imp.get_magic() + \
+                u'\xff\xff\xff\xff'.encode('iso-8859-15')
+
+        def write_file(filename, data, mode):
+            if zip:
+                info = ZipInfo(filename)
+                info.external_attr = 0755 << 16L
+                zip_file.writestr(info, data)
+            else:
+                f = open(os.path.join(target, filename), mode)
+                try:
+                    f.write(data)
+                finally:
+                    f.close()
+
+        if zip is not None:
+            from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
+            zip_file = ZipFile(target, 'w', dict(deflated=ZIP_DEFLATED,
+                                                 stored=ZIP_STORED)[zip])
+            log_function('Compiling into Zip archive "%s"' % target)
+        else:
+            if not os.path.isdir(target):
+                os.makedirs(target)
+            log_function('Compiling into folder "%s"' % target)
+
+        try:
+            for name in self.list_templates(extensions, filter_func):
+                source, filename, _ = self.loader.get_source(self, name)
+                try:
+                    code = self.compile(source, name, filename, True, True)
+                except TemplateSyntaxError, e:
+                    if not ignore_errors:
+                        raise
+                    log_function('Could not compile "%s": %s' % (name, e))
+                    continue
+
+                filename = ModuleLoader.get_module_filename(name)
+
+                if py_compile:
+                    c = self._compile(code, _encode_filename(filename))
+                    write_file(filename + 'c', py_header +
+                               marshal.dumps(c), 'wb')
+                    log_function('Byte-compiled "%s" as %s' %
+                                 (name, filename + 'c'))
+                else:
+                    write_file(filename, code, 'w')
+                    log_function('Compiled "%s" as %s' % (name, filename))
+        finally:
+            if zip:
+                zip_file.close()
+
+        log_function('Finished compiling templates')
+
+    def list_templates(self, extensions=None, filter_func=None):
+        """Returns a list of templates for this environment.  This requires
+        that the loader supports the loader's
+        :meth:`~BaseLoader.list_templates` method.
+
+        If there are other files in the template folder besides the
+        actual templates, the returned list can be filtered.  There are two
+        ways: either `extensions` is set to a list of file extensions for
+        templates, or a `filter_func` can be provided which is a callable that
+        is passed a template name and should return `True` if it should end up
+        in the result list.
+
+        If the loader does not support that, a :exc:`TypeError` is raised.
+        """
+        x = self.loader.list_templates()
+        if extensions is not None:
+            if filter_func is not None:
+                raise TypeError('either extensions or filter_func '
+                                'can be passed, but not both')
+            filter_func = lambda x: '.' in x and \
+                                    x.rsplit('.', 1)[1] in extensions
+        if filter_func is not None:
+            x = filter(filter_func, x)
+        return x
+
+    def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
+        """Exception handling helper.  This is used internally to either raise
+        rewritten exceptions or return a rendered traceback for the template.
+        """
+        global _make_traceback
+        if exc_info is None:
+            exc_info = sys.exc_info()
+
+        # the debugging module is imported when it's used for the first time.
+        # we're doing a lot of stuff there and for applications that do not
+        # get any exceptions in template rendering there is no need to load
+        # all of that.
+        if _make_traceback is None:
+            from ambari_jinja2.debug import make_traceback as _make_traceback
+        traceback = _make_traceback(exc_info, source_hint)
+        if rendered and self.exception_formatter is not None:
+            return self.exception_formatter(traceback)
+        if self.exception_handler is not None:
+            self.exception_handler(traceback)
+        exc_type, exc_value, tb = traceback.standard_exc_info
+        raise exc_type, exc_value, tb
+
+    def join_path(self, template, parent):
+        """Join a template with the parent.  By default all the lookups are
+        relative to the loader root so this method returns the `template`
+        parameter unchanged, but if the paths should be relative to the
+        parent template, this function can be used to calculate the real
+        template name.
+
+        Subclasses may override this method and implement template path
+        joining here.
+        """
+        return template
+
+    @internalcode
+    def _load_template(self, name, globals):
+        if self.loader is None:
+            raise TypeError('no loader for this environment specified')
+        if self.cache is not None:
+            template = self.cache.get(name)
+            if template is not None and (not self.auto_reload or \
+                                         template.is_up_to_date):
+                return template
+        template = self.loader.load(self, name, globals)
+        if self.cache is not None:
+            self.cache[name] = template
+        return template
+
+    @internalcode
+    def get_template(self, name, parent=None, globals=None):
+        """Load a template from the loader.  If a loader is configured this
+        method ask the loader for the template and returns a :class:`Template`.
+        If the `parent` parameter is not `None`, :meth:`join_path` is called
+        to get the real template name before loading.
+
+        The `globals` parameter can be used to provide template wide globals.
+        These variables are available in the context at render time.
+
+        If the template does not exist a :exc:`TemplateNotFound` exception is
+        raised.
+
+        .. versionchanged:: 2.4
+           If `name` is a :class:`Template` object it is returned from the
+           function unchanged.
+        """
+        if isinstance(name, Template):
+            return name
+        if parent is not None:
+            name = self.join_path(name, parent)
+        return self._load_template(name, self.make_globals(globals))
+
+    @internalcode
+    def select_template(self, names, parent=None, globals=None):
+        """Works like :meth:`get_template` but tries a number of templates
+        before it fails.  If it cannot find any of the templates, it will
+        raise a :exc:`TemplatesNotFound` exception.
+
+        .. versionadded:: 2.3
+
+        .. versionchanged:: 2.4
+           If `names` contains a :class:`Template` object it is returned
+           from the function unchanged.
+        """
+        if not names:
+            raise TemplatesNotFound(message=u'Tried to select from an empty list '
+                                            u'of templates.')
+        globals = self.make_globals(globals)
+        for name in names:
+            if isinstance(name, Template):
+                return name
+            if parent is not None:
+                name = self.join_path(name, parent)
+            try:
+                return self._load_template(name, globals)
+            except TemplateNotFound:
+                pass
+        raise TemplatesNotFound(names)
+
+    @internalcode
+    def get_or_select_template(self, template_name_or_list,
+                               parent=None, globals=None):
+        """Does a typecheck and dispatches to :meth:`select_template`
+        if an iterable of template names is given, otherwise to
+        :meth:`get_template`.
+
+        .. versionadded:: 2.3
+        """
+        if isinstance(template_name_or_list, basestring):
+            return self.get_template(template_name_or_list, parent, globals)
+        elif isinstance(template_name_or_list, Template):
+            return template_name_or_list
+        return self.select_template(template_name_or_list, parent, globals)
+
+    def from_string(self, source, globals=None, template_class=None):
+        """Load a template from a string.  This parses the source given and
+        returns a :class:`Template` object.
+        """
+        globals = self.make_globals(globals)
+        cls = template_class or self.template_class
+        return cls.from_code(self, self.compile(source), globals, None)
+
+    def make_globals(self, d):
+        """Return a dict for the globals."""
+        if not d:
+            return self.globals
+        return dict(self.globals, **d)
+
+
+class Template(object):
+    """The central template object.  This class represents a compiled template
+    and is used to evaluate it.
+
+    Normally the template object is generated from an :class:`Environment` but
+    it also has a constructor that makes it possible to create a template
+    instance directly using the constructor.  It takes the same arguments as
+    the environment constructor but it's not possible to specify a loader.
+
+    Every template object has a few methods and members that are guaranteed
+    to exist.  However it's important that a template object should be
+    considered immutable.  Modifications on the object are not supported.
+
+    Template objects created from the constructor rather than an environment
+    do have an `environment` attribute that points to a temporary environment
+    that is probably shared with other templates created with the constructor
+    and compatible settings.
+
+    >>> template = Template('Hello {{ name }}!')
+    >>> template.render(name='John Doe')
+    u'Hello John Doe!'
+
+    >>> stream = template.stream(name='John Doe')
+    >>> stream.next()
+    u'Hello John Doe!'
+    >>> stream.next()
+    Traceback (most recent call last):
+        ...
+    StopIteration
+    """
+
+    def __new__(cls, source,
+                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,
+                line_statement_prefix=LINE_STATEMENT_PREFIX,
+                line_comment_prefix=LINE_COMMENT_PREFIX,
+                trim_blocks=TRIM_BLOCKS,
+                newline_sequence=NEWLINE_SEQUENCE,
+                extensions=(),
+                optimized=True,
+                undefined=Undefined,
+                finalize=None,
+                autoescape=False):
+        env = get_spontaneous_environment(
+            block_start_string, block_end_string, variable_start_string,
+            variable_end_string, comment_start_string, comment_end_string,
+            line_statement_prefix, line_comment_prefix, trim_blocks,
+            newline_sequence, frozenset(extensions), optimized, undefined,
+            finalize, autoescape, None, 0, False, None)
+        return env.from_string(source, template_class=cls)
+
+    @classmethod
+    def from_code(cls, environment, code, globals, uptodate=None):
+        """Creates a template object from compiled code and the globals.  This
+        is used by the loaders and environment to create a template object.
+        """
+        namespace = {
+            'environment':  environment,
+            '__file__':     code.co_filename
+        }
+        exec code in namespace
+        rv = cls._from_namespace(environment, namespace, globals)
+        rv._uptodate = uptodate
+        return rv
+
+    @classmethod
+    def from_module_dict(cls, environment, module_dict, globals):
+        """Creates a template object from a module.  This is used by the
+        module loader to create a template object.
+
+        .. versionadded:: 2.4
+        """
+        return cls._from_namespace(environment, module_dict, globals)
+
+    @classmethod
+    def _from_namespace(cls, environment, namespace, globals):
+        t = object.__new__(cls)
+        t.environment = environment
+        t.globals = globals
+        t.name = namespace['name']
+        t.filename = namespace['__file__']
+        t.blocks = namespace['blocks']
+
+        # render function and module
+        t.root_render_func = namespace['root']
+        t._module = None
+
+        # debug and loader helpers
+        t._debug_info = namespace['debug_info']
+        t._uptodate = None
+
+        # store the reference
+        namespace['environment'] = environment
+        namespace['__jinja_template__'] = t
+
+        return t
+
+    def render(self, *args, **kwargs):
+        """This method accepts the same arguments as the `dict` constructor:
+        A dict, a dict subclass or some keyword arguments.  If no arguments
+        are given the context will be empty.  These two calls do the same::
+
+            template.render(knights='that say nih')
+            template.render({'knights': 'that say nih'})
+
+        This will return the rendered template as unicode string.
+        """
+        vars = dict(*args, **kwargs)
+        try:
+            return concat(self.root_render_func(self.new_context(vars)))
+        except:
+            exc_info = sys.exc_info()
+        return self.environment.handle_exception(exc_info, True)
+
+    def stream(self, *args, **kwargs):
+        """Works exactly like :meth:`generate` but returns a
+        :class:`TemplateStream`.
+        """
+        return TemplateStream(self.generate(*args, **kwargs))
+
+    def generate(self, *args, **kwargs):
+        """For very large templates it can be useful to not render the whole
+        template at once but evaluate each statement after another and yield
+        piece for piece.  This method basically does exactly that and returns
+        a generator that yields one item after another as unicode strings.
+
+        It accepts the same arguments as :meth:`render`.
+        """
+        vars = dict(*args, **kwargs)
+        try:
+            for event in self.root_render_func(self.new_context(vars)):
+                yield event
+        except:
+            exc_info = sys.exc_info()
+        else:
+            return
+        yield self.environment.handle_exception(exc_info, True)
+
+    def new_context(self, vars=None, shared=False, locals=None):
+        """Create a new :class:`Context` for this template.  The vars
+        provided will be passed to the template.  Per default the globals
+        are added to the context.  If shared is set to `True` the data
+        is passed as it to the context without adding the globals.
+
+        `locals` can be a dict of local variables for internal usage.
+        """
+        return new_context(self.environment, self.name, self.blocks,
+                           vars, shared, self.globals, locals)
+
+    def make_module(self, vars=None, shared=False, locals=None):
+        """This method works like the :attr:`module` attribute when called
+        without arguments but it will evaluate the template on every call
+        rather than caching it.  It's also possible to provide
+        a dict which is then used as context.  The arguments are the same
+        as for the :meth:`new_context` method.
+        """
+        return TemplateModule(self, self.new_context(vars, shared, locals))
+
+    @property
+    def module(self):
+        """The template as module.  This is used for imports in the
+        template runtime but is also useful if one wants to access
+        exported template variables from the Python layer:
+
+        >>> t = Template('{% macro foo() %}42{% endmacro %}23')
+        >>> unicode(t.module)
+        u'23'
+        >>> t.module.foo()
+        u'42'
+        """
+        if self._module is not None:
+            return self._module
+        self._module = rv = self.make_module()
+        return rv
+
+    def get_corresponding_lineno(self, lineno):
+        """Return the source line number of a line number in the
+        generated bytecode as they are not in sync.
+        """
+        for template_line, code_line in reversed(self.debug_info):
+            if code_line <= lineno:
+                return template_line
+        return 1
+
+    @property
+    def is_up_to_date(self):
+        """If this variable is `False` there is a newer version available."""
+        if self._uptodate is None:
+            return True
+        return self._uptodate()
+
+    @property
+    def debug_info(self):
+        """The debug info mapping."""
+        return [tuple(map(int, x.split('='))) for x in
+                self._debug_info.split('&')]
+
+    def __repr__(self):
+        if self.name is None:
+            name = 'memory:%x' % id(self)
+        else:
+            name = repr(self.name)
+        return '<%s %s>' % (self.__class__.__name__, name)
+
+
+class TemplateModule(object):
+    """Represents an imported template.  All the exported names of the
+    template are available as attributes on this object.  Additionally
+    converting it into an unicode- or bytestrings renders the contents.
+    """
+
+    def __init__(self, template, context):
+        self._body_stream = list(template.root_render_func(context))
+        self.__dict__.update(context.get_exported())
+        self.__name__ = template.name
+
+    def __html__(self):
+        return Markup(concat(self._body_stream))
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        return concat(self._body_stream)
+
+    def __repr__(self):
+        if self.__name__ is None:
+            name = 'memory:%x' % id(self)
+        else:
+            name = repr(self.__name__)
+        return '<%s %s>' % (self.__class__.__name__, name)
+
+
+class TemplateExpression(object):
+    """The :meth:`ambari_jinja2.Environment.compile_expression` method returns an
+    instance of this object.  It encapsulates the expression-like access
+    to the template with an expression it wraps.
+    """
+
+    def __init__(self, template, undefined_to_none):
+        self._template = template
+        self._undefined_to_none = undefined_to_none
+
+    def __call__(self, *args, **kwargs):
+        context = self._template.new_context(dict(*args, **kwargs))
+        consume(self._template.root_render_func(context))
+        rv = context.vars['result']
+        if self._undefined_to_none and isinstance(rv, Undefined):
+            rv = None
+        return rv
+
+
+class TemplateStream(object):
+    """A template stream works pretty much like an ordinary python generator
+    but it can buffer multiple items to reduce the number of total iterations.
+    Per default the output is unbuffered which means that for every unbuffered
+    instruction in the template one unicode string is yielded.
+
+    If buffering is enabled with a buffer size of 5, five items are combined
+    into a new unicode string.  This is mainly useful if you are streaming
+    big templates to a client via WSGI which flushes after each iteration.
+    """
+
+    def __init__(self, gen):
+        self._gen = gen
+        self.disable_buffering()
+
+    def dump(self, fp, encoding=None, errors='strict'):
+        """Dump the complete stream into a file or file-like object.
+        Per default unicode strings are written, if you want to encode
+        before writing specifiy an `encoding`.
+
+        Example usage::
+
+            Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
+        """
+        close = False
+        if isinstance(fp, basestring):
+            fp = file(fp, 'w')
+            close = True
+        try:
+            if encoding is not None:
+                iterable = (x.encode(encoding, errors) for x in self)
+            else:
+                iterable = self
+            if hasattr(fp, 'writelines'):
+                fp.writelines(iterable)
+            else:
+                for item in iterable:
+                    fp.write(item)
+        finally:
+            if close:
+                fp.close()
+
+    def disable_buffering(self):
+        """Disable the output buffering."""
+        self._next = self._gen.next
+        self.buffered = False
+
+    def enable_buffering(self, size=5):
+        """Enable buffering.  Buffer `size` items before yielding them."""
+        if size <= 1:
+            raise ValueError('buffer size too small')
+
+        def generator(next):
+            buf = []
+            c_size = 0
+            push = buf.append
+
+            while 1:
+                try:
+                    while c_size < size:
+                        c = next()
+                        push(c)
+                        if c:
+                            c_size += 1
+                except StopIteration:
+                    if not c_size:
+                        return
+                yield concat(buf)
+                del buf[:]
+                c_size = 0
+
+        self.buffered = True
+        self._next = generator(self._gen.next).next
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        return self._next()
+
+
+# hook in default template class.  if anyone reads this comment: ignore that
+# it's possible to use custom templates ;-)
+Environment.template_class = Template

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py
new file mode 100644
index 0000000..346c706
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/exceptions.py
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.exceptions
+    ~~~~~~~~~~~~~~~~~
+
+    Jinja exceptions.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+
+
+class TemplateError(Exception):
+    """Baseclass for all template errors."""
+
+    def __init__(self, message=None):
+        if message is not None:
+            message = unicode(message).encode('utf-8')
+        Exception.__init__(self, message)
+
+    @property
+    def message(self):
+        if self.args:
+            message = self.args[0]
+            if message is not None:
+                return message.decode('utf-8', 'replace')
+
+
+class TemplateNotFound(IOError, LookupError, TemplateError):
+    """Raised if a template does not exist."""
+
+    # looks weird, but removes the warning descriptor that just
+    # bogusly warns us about message being deprecated
+    message = None
+
+    def __init__(self, name, message=None):
+        IOError.__init__(self)
+        if message is None:
+            message = name
+        self.message = message
+        self.name = name
+        self.templates = [name]
+
+    def __str__(self):
+        return self.message.encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        return self.message
+
+
+class TemplatesNotFound(TemplateNotFound):
+    """Like :class:`TemplateNotFound` but raised if multiple templates
+    are selected.  This is a subclass of :class:`TemplateNotFound`
+    exception, so just catching the base exception will catch both.
+
+    .. versionadded:: 2.2
+    """
+
+    def __init__(self, names=(), message=None):
+        if message is None:
+            message = u'non of the templates given were found: ' + \
+                      u', '.join(map(unicode, names))
+        TemplateNotFound.__init__(self, names and names[-1] or None, message)
+        self.templates = list(names)
+
+
+class TemplateSyntaxError(TemplateError):
+    """Raised to tell the user that there is a problem with the template."""
+
+    def __init__(self, message, lineno, name=None, filename=None):
+        TemplateError.__init__(self, message)
+        self.lineno = lineno
+        self.name = name
+        self.filename = filename
+        self.source = None
+
+        # this is set to True if the debug.translate_syntax_error
+        # function translated the syntax error into a new traceback
+        self.translated = False
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+    # unicode goes after __str__ because we configured 2to3 to rename
+    # __unicode__ to __str__.  because the 2to3 tree is not designed to
+    # remove nodes from it, we leave the above __str__ around and let
+    # it override at runtime.
+    def __unicode__(self):
+        # for translated errors we only return the message
+        if self.translated:
+            return self.message
+
+        # otherwise attach some stuff
+        location = 'line %d' % self.lineno
+        name = self.filename or self.name
+        if name:
+            location = 'File "%s", %s' % (name, location)
+        lines = [self.message, '  ' + location]
+
+        # if the source is set, add the line to the output
+        if self.source is not None:
+            try:
+                line = self.source.splitlines()[self.lineno - 1]
+            except IndexError:
+                line = None
+            if line:
+                lines.append('    ' + line.strip())
+
+        return u'\n'.join(lines)
+
+
+class TemplateAssertionError(TemplateSyntaxError):
+    """Like a template syntax error, but covers cases where something in the
+    template caused an error at compile time that wasn't necessarily caused
+    by a syntax error.  However it's a direct subclass of
+    :exc:`TemplateSyntaxError` and has the same attributes.
+    """
+
+
+class TemplateRuntimeError(TemplateError):
+    """A generic runtime error in the template engine.  Under some situations
+    Jinja may raise this exception.
+    """
+
+
+class UndefinedError(TemplateRuntimeError):
+    """Raised if a template tries to operate on :class:`Undefined`."""
+
+
+class SecurityError(TemplateRuntimeError):
+    """Raised if a template tries to do something insecure if the
+    sandbox is enabled.
+    """
+
+
+class FilterArgumentError(TemplateRuntimeError):
+    """This error is raised if a filter was called with inappropriate
+    arguments
+    """

http://git-wip-us.apache.org/repos/asf/ambari/blob/658360a5/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py
new file mode 100644
index 0000000..20149d1
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/ext.py
@@ -0,0 +1,610 @@
+# -*- coding: utf-8 -*-
+"""
+    ambari_jinja2.ext
+    ~~~~~~~~~~
+
+    Jinja extensions allow to add custom tags similar to the way django custom
+    tags work.  By default two example extensions exist: an i18n and a cache
+    extension.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD.
+"""
+from collections import deque
+from ambari_jinja2 import nodes
+from ambari_jinja2.defaults import *
+from ambari_jinja2.environment import Environment
+from ambari_jinja2.runtime import Undefined, concat
+from ambari_jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
+from ambari_jinja2.utils import contextfunction, import_string, Markup, next
+
+
+# the only real useful gettext functions for a Jinja template.  Note
+# that ugettext must be assigned to gettext as Jinja doesn't support
+# non unicode strings.
+GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext')
+
+
+class ExtensionRegistry(type):
+    """Gives the extension an unique identifier."""
+
+    def __new__(cls, name, bases, d):
+        rv = type.__new__(cls, name, bases, d)
+        rv.identifier = rv.__module__ + '.' + rv.__name__
+        return rv
+
+
+class Extension(object):
+    """Extensions can be used to add extra functionality to the Jinja template
+    system at the parser level.  Custom extensions are bound to an environment
+    but may not store environment specific data on `self`.  The reason for
+    this is that an extension can be bound to another environment (for
+    overlays) by creating a copy and reassigning the `environment` attribute.
+
+    As extensions are created by the environment they cannot accept any
+    arguments for configuration.  One may want to work around that by using
+    a factory function, but that is not possible as extensions are identified
+    by their import name.  The correct way to configure the extension is
+    storing the configuration values on the environment.  Because this way the
+    environment ends up acting as central configuration storage the
+    attributes may clash which is why extensions have to ensure that the names
+    they choose for configuration are not too generic.  ``prefix`` for example
+    is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
+    name as includes the name of the extension (fragment cache).
+    """
+    __metaclass__ = ExtensionRegistry
+
+    #: if this extension parses this is the list of tags it's listening to.
+    tags = set()
+
+    #: the priority of that extension.  This is especially useful for
+    #: extensions that preprocess values.  A lower value means higher
+    #: priority.
+    #:
+    #: .. versionadded:: 2.4
+    priority = 100
+
+    def __init__(self, environment):
+        self.environment = environment
+
+    def bind(self, environment):
+        """Create a copy of this extension bound to another environment."""
+        rv = object.__new__(self.__class__)
+        rv.__dict__.update(self.__dict__)
+        rv.environment = environment
+        return rv
+
+    def preprocess(self, source, name, filename=None):
+        """This method is called before the actual lexing and can be used to
+        preprocess the source.  The `filename` is optional.  The return value
+        must be the preprocessed source.
+        """
+        return source
+
+    def filter_stream(self, stream):
+        """It's passed a :class:`~ambari_jinja2.lexer.TokenStream` that can be used
+        to filter tokens returned.  This method has to return an iterable of
+        :class:`~ambari_jinja2.lexer.Token`\s, but it doesn't have to return a
+        :class:`~ambari_jinja2.lexer.TokenStream`.
+
+        In the `ext` folder of the Jinja2 source distribution there is a file
+        called `inlinegettext.py` which implements a filter that utilizes this
+        method.
+        """
+        return stream
+
+    def parse(self, parser):
+        """If any of the :attr:`tags` matched this method is called with the
+        parser as first argument.  The token the parser stream is pointing at
+        is the name token that matched.  This method has to return one or a
+        list of multiple nodes.
+        """
+        raise NotImplementedError()
+
+    def attr(self, name, lineno=None):
+        """Return an attribute node for the current extension.  This is useful
+        to pass constants on extensions to generated template code::
+
+            self.attr('_my_attribute', lineno=lineno)
+        """
+        return nodes.ExtensionAttribute(self.identifier, name, lineno=lineno)
+
+    def call_method(self, name, args=None, kwargs=None, dyn_args=None,
+                    dyn_kwargs=None, lineno=None):
+        """Call a method of the extension.  This is a shortcut for
+        :meth:`attr` + :class:`ambari_jinja2.nodes.Call`.
+        """
+        if args is None:
+            args = []
+        if kwargs is None:
+            kwargs = []
+        return nodes.Call(self.attr(name, lineno=lineno), args, kwargs,
+                          dyn_args, dyn_kwargs, lineno=lineno)
+
+
+@contextfunction
+def _gettext_alias(__context, *args, **kwargs):
+    return __context.call(__context.resolve('gettext'), *args, **kwargs)
+
+
+def _make_new_gettext(func):
+    @contextfunction
+    def gettext(__context, __string, **variables):
+        rv = __context.call(func, __string)
+        if __context.eval_ctx.autoescape:
+            rv = Markup(rv)
+        return rv % variables
+    return gettext
+
+
+def _make_new_ngettext(func):
+    @contextfunction
+    def ngettext(__context, __singular, __plural, __num, **variables):
+        variables.setdefault('num', __num)
+        rv = __context.call(func, __singular, __plural, __num)
+        if __context.eval_ctx.autoescape:
+            rv = Markup(rv)
+        return rv % variables
+    return ngettext
+
+
+class InternationalizationExtension(Extension):
+    """This extension adds gettext support to Jinja2."""
+    tags = set(['trans'])
+
+    # TODO: the i18n extension is currently reevaluating values in a few
+    # situations.  Take this example:
+    #   {% trans count=something() %}{{ count }} foo{% pluralize
+    #     %}{{ count }} fooss{% endtrans %}
+    # something is called twice here.  One time for the gettext value and
+    # the other time for the n-parameter of the ngettext function.
+
+    def __init__(self, environment):
+        Extension.__init__(self, environment)
+        environment.globals['_'] = _gettext_alias
+        environment.extend(
+            install_gettext_translations=self._install,
+            install_null_translations=self._install_null,
+            install_gettext_callables=self._install_callables,
+            uninstall_gettext_translations=self._uninstall,
+            extract_translations=self._extract,
+            newstyle_gettext=False
+        )
+
+    def _install(self, translations, newstyle=None):
+        gettext = getattr(translations, 'ugettext', None)
+        if gettext is None:
+            gettext = translations.gettext
+        ngettext = getattr(translations, 'ungettext', None)
+        if ngettext is None:
+            ngettext = translations.ngettext
+        self._install_callables(gettext, ngettext, newstyle)
+
+    def _install_null(self, newstyle=None):
+        self._install_callables(
+            lambda x: x,
+            lambda s, p, n: (n != 1 and (p,) or (s,))[0],
+            newstyle
+        )
+
+    def _install_callables(self, gettext, ngettext, newstyle=None):
+        if newstyle is not None:
+            self.environment.newstyle_gettext = newstyle
+        if self.environment.newstyle_gettext:
+            gettext = _make_new_gettext(gettext)
+            ngettext = _make_new_ngettext(ngettext)
+        self.environment.globals.update(
+            gettext=gettext,
+            ngettext=ngettext
+        )
+
+    def _uninstall(self, translations):
+        for key in 'gettext', 'ngettext':
+            self.environment.globals.pop(key, None)
+
+    def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
+        if isinstance(source, basestring):
+            source = self.environment.parse(source)
+        return extract_from_ast(source, gettext_functions)
+
+    def parse(self, parser):
+        """Parse a translatable tag."""
+        lineno = next(parser.stream).lineno
+        num_called_num = False
+
+        # find all the variables referenced.  Additionally a variable can be
+        # defined in the body of the trans block too, but this is checked at
+        # a later state.
+        plural_expr = None
+        variables = {}
+        while parser.stream.current.type != 'block_end':
+            if variables:
+                parser.stream.expect('comma')
+
+            # skip colon for python compatibility
+            if parser.stream.skip_if('colon'):
+                break
+
+            name = parser.stream.expect('name')
+            if name.value in variables:
+                parser.fail('translatable variable %r defined twice.' %
+                            name.value, name.lineno,
+                            exc=TemplateAssertionError)
+
+            # expressions
+            if parser.stream.current.type == 'assign':
+                next(parser.stream)
+                variables[name.value] = var = parser.parse_expression()
+            else:
+                variables[name.value] = var = nodes.Name(name.value, 'load')
+
+            if plural_expr is None:
+                plural_expr = var
+                num_called_num = name.value == 'num'
+
+        parser.stream.expect('block_end')
+
+        plural = plural_names = None
+        have_plural = False
+        referenced = set()
+
+        # now parse until endtrans or pluralize
+        singular_names, singular = self._parse_block(parser, True)
+        if singular_names:
+            referenced.update(singular_names)
+            if plural_expr is None:
+                plural_expr = nodes.Name(singular_names[0], 'load')
+                num_called_num = singular_names[0] == 'num'
+
+        # if we have a pluralize block, we parse that too
+        if parser.stream.current.test('name:pluralize'):
+            have_plural = True
+            next(parser.stream)
+            if parser.stream.current.type != 'block_end':
+                name = parser.stream.expect('name')
+                if name.value not in variables:
+                    parser.fail('unknown variable %r for pluralization' %
+                                name.value, name.lineno,
+                                exc=TemplateAssertionError)
+                plural_expr = variables[name.value]
+                num_called_num = name.value == 'num'
+            parser.stream.expect('block_end')
+            plural_names, plural = self._parse_block(parser, False)
+            next(parser.stream)
+            referenced.update(plural_names)
+        else:
+            next(parser.stream)
+
+        # register free names as simple name expressions
+        for var in referenced:
+            if var not in variables:
+                variables[var] = nodes.Name(var, 'load')
+
+        if not have_plural:
+            plural_expr = None
+        elif plural_expr is None:
+            parser.fail('pluralize without variables', lineno)
+
+        node = self._make_node(singular, plural, variables, plural_expr,
+                               bool(referenced),
+                               num_called_num and have_plural)
+        node.set_lineno(lineno)
+        return node
+
+    def _parse_block(self, parser, allow_pluralize):
+        """Parse until the next block tag with a given name."""
+        referenced = []
+        buf = []
+        while 1:
+            if parser.stream.current.type == 'data':
+                buf.append(parser.stream.current.value.replace('%', '%%'))
+                next(parser.stream)
+            elif parser.stream.current.type == 'variable_begin':
+                next(parser.stream)
+                name = parser.stream.expect('name').value
+                referenced.append(name)
+                buf.append('%%(%s)s' % name)
+                parser.stream.expect('variable_end')
+            elif parser.stream.current.type == 'block_begin':
+                next(parser.stream)
+                if parser.stream.current.test('name:endtrans'):
+                    break
+                elif parser.stream.current.test('name:pluralize'):
+                    if allow_pluralize:
+                        break
+                    parser.fail('a translatable section can have only one '
+                                'pluralize section')
+                parser.fail('control structures in translatable sections are '
+                            'not allowed')
+            elif parser.stream.eos:
+                parser.fail('unclosed translation block')
+            else:
+                assert False, 'internal parser error'
+
+        return referenced, concat(buf)
+
+    def _make_node(self, singular, plural, variables, plural_expr,
+                   vars_referenced, num_called_num):
+        """Generates a useful node from the data provided."""
+        # no variables referenced?  no need to escape for old style
+        # gettext invocations only if there are vars.
+        if not vars_referenced and not self.environment.newstyle_gettext:
+            singular = singular.replace('%%', '%')
+            if plural:
+                plural = plural.replace('%%', '%')
+
+        # singular only:
+        if plural_expr is None:
+            gettext = nodes.Name('gettext', 'load')
+            node = nodes.Call(gettext, [nodes.Const(singular)],
+                              [], None, None)
+
+        # singular and plural
+        else:
+            ngettext = nodes.Name('ngettext', 'load')
+            node = nodes.Call(ngettext, [
+                nodes.Const(singular),
+                nodes.Const(plural),
+                plural_expr
+            ], [], None, None)
+
+        # in case newstyle gettext is used, the method is powerful
+        # enough to handle the variable expansion and autoescape
+        # handling itself
+        if self.environment.newstyle_gettext:
+            for key, value in variables.iteritems():
+                # the function adds that later anyways in case num was
+                # called num, so just skip it.
+                if num_called_num and key == 'num':
+                    continue
+                node.kwargs.append(nodes.Keyword(key, value))
+
+        # otherwise do that here
+        else:
+            # mark the return value as safe if we are in an
+            # environment with autoescaping turned on
+            node = nodes.MarkSafeIfAutoescape(node)
+            if variables:
+                node = nodes.Mod(node, nodes.Dict([
+                    nodes.Pair(nodes.Const(key), value)
+                    for key, value in variables.items()
+                ]))
+        return nodes.Output([node])
+
+
+class ExprStmtExtension(Extension):
+    """Adds a `do` tag to Jinja2 that works like the print statement just
+    that it doesn't print the return value.
+    """
+    tags = set(['do'])
+
+    def parse(self, parser):
+        node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
+        node.node = parser.parse_tuple()
+        return node
+
+
+class LoopControlExtension(Extension):
+    """Adds break and continue to the template engine."""
+    tags = set(['break', 'continue'])
+
+    def parse(self, parser):
+        token = next(parser.stream)
+        if token.value == 'break':
+            return nodes.Break(lineno=token.lineno)
+        return nodes.Continue(lineno=token.lineno)
+
+
+class WithExtension(Extension):
+    """Adds support for a django-like with block."""
+    tags = set(['with'])
+
+    def parse(self, parser):
+        node = nodes.Scope(lineno=next(parser.stream).lineno)
+        assignments = []
+        while parser.stream.current.type != 'block_end':
+            lineno = parser.stream.current.lineno
+            if assignments:
+                parser.stream.expect('comma')
+            target = parser.parse_assign_target()
+            parser.stream.expect('assign')
+            expr = parser.parse_expression()
+            assignments.append(nodes.Assign(target, expr, lineno=lineno))
+        node.body = assignments + \
+            list(parser.parse_statements(('name:endwith',),
+                                         drop_needle=True))
+        return node
+
+
+class AutoEscapeExtension(Extension):
+    """Changes auto escape rules for a scope."""
+    tags = set(['autoescape'])
+
+    def parse(self, parser):
+        node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
+        node.options = [
+            nodes.Keyword('autoescape', parser.parse_expression())
+        ]
+        node.body = parser.parse_statements(('name:endautoescape',),
+                                            drop_needle=True)
+        return nodes.Scope([node])
+
+
+def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
+                     babel_style=True):
+    """Extract localizable strings from the given template node.  Per
+    default this function returns matches in babel style that means non string
+    parameters as well as keyword arguments are returned as `None`.  This
+    allows Babel to figure out what you really meant if you are using
+    gettext functions that allow keyword arguments for placeholder expansion.
+    If you don't want that behavior set the `babel_style` parameter to `False`
+    which causes only strings to be returned and parameters are always stored
+    in tuples.  As a consequence invalid gettext calls (calls without a single
+    string parameter or string parameters after non-string parameters) are
+    skipped.
+
+    This example explains the behavior:
+
+    >>> from ambari_jinja2 import Environment
+    >>> env = Environment()
+    >>> node = env.parse('{{ (_("foo"), _(), ngettext("foo", "bar", 42)) }}')
+    >>> list(extract_from_ast(node))
+    [(1, '_', 'foo'), (1, '_', ()), (1, 'ngettext', ('foo', 'bar', None))]
+    >>> list(extract_from_ast(node, babel_style=False))
+    [(1, '_', ('foo',)), (1, 'ngettext', ('foo', 'bar'))]
+
+    For every string found this function yields a ``(lineno, function,
+    message)`` tuple, where:
+
+    * ``lineno`` is the number of the line on which the string was found,
+    * ``function`` is the name of the ``gettext`` function used (if the
+      string was extracted from embedded Python code), and
+    *  ``message`` is the string itself (a ``unicode`` object, or a tuple
+       of ``unicode`` objects for functions with multiple string arguments).
+
+    This extraction function operates on the AST and is because of that unable
+    to extract any comments.  For comment support you have to use the babel
+    extraction interface or extract comments yourself.
+    """
+    for node in node.find_all(nodes.Call):
+        if not isinstance(node.node, nodes.Name) or \
+           node.node.name not in gettext_functions:
+            continue
+
+        strings = []
+        for arg in node.args:
+            if isinstance(arg, nodes.Const) and \
+               isinstance(arg.value, basestring):
+                strings.append(arg.value)
+            else:
+                strings.append(None)
+
+        for arg in node.kwargs:
+            strings.append(None)
+        if node.dyn_args is not None:
+            strings.append(None)
+        if node.dyn_kwargs is not None:
+            strings.append(None)
+
+        if not babel_style:
+            strings = tuple(x for x in strings if x is not None)
+            if not strings:
+                continue
+        else:
+            if len(strings) == 1:
+                strings = strings[0]
+            else:
+                strings = tuple(strings)
+        yield node.lineno, node.node.name, strings
+
+
+class _CommentFinder(object):
+    """Helper class to find comments in a token stream.  Can only
+    find comments for gettext calls forwards.  Once the comment
+    from line 4 is found, a comment for line 1 will not return a
+    usable value.
+    """
+
+    def __init__(self, tokens, comment_tags):
+        self.tokens = tokens
+        self.comment_tags = comment_tags
+        self.offset = 0
+        self.last_lineno = 0
+
+    def find_backwards(self, offset):
+        try:
+            for _, token_type, token_value in \
+                    reversed(self.tokens[self.offset:offset]):
+                if token_type in ('comment', 'linecomment'):
+                    try:
+                        prefix, comment = token_value.split(None, 1)
+                    except ValueError:
+                        continue
+                    if prefix in self.comment_tags:
+                        return [comment.rstrip()]
+            return []
+        finally:
+            self.offset = offset
+
+    def find_comments(self, lineno):
+        if not self.comment_tags or self.last_lineno > lineno:
+            return []
+        for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset:]):
+            if token_lineno > lineno:
+                return self.find_backwards(self.offset + idx)
+        return self.find_backwards(len(self.tokens))
+
+
+def babel_extract(fileobj, keywords, comment_tags, options):
+    """Babel extraction method for Jinja templates.
+
+    .. versionchanged:: 2.3
+       Basic support for translation comments was added.  If `comment_tags`
+       is now set to a list of keywords for extraction, the extractor will
+       try to find the best preceeding comment that begins with one of the
+       keywords.  For best results, make sure to not have more than one
+       gettext call in one line of code and the matching comment in the
+       same line or the line before.
+
+    .. versionchanged:: 2.5.1
+       The `newstyle_gettext` flag can be set to `True` to enable newstyle
+       gettext calls.
+
+    :param fileobj: the file-like object the messages should be extracted from
+    :param keywords: a list of keywords (i.e. function names) that should be
+                     recognized as translation functions
+    :param comment_tags: a list of translator tags to search for and include
+                         in the results.
+    :param options: a dictionary of additional options (optional)
+    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
+             (comments will be empty currently)
+    """
+    extensions = set()
+    for extension in options.get('extensions', '').split(','):
+        extension = extension.strip()
+        if not extension:
+            continue
+        extensions.add(import_string(extension))
+    if InternationalizationExtension not in extensions:
+        extensions.add(InternationalizationExtension)
+
+    def getbool(options, key, default=False):
+        options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true')
+
+    environment = Environment(
+        options.get('block_start_string', BLOCK_START_STRING),
+        options.get('block_end_string', BLOCK_END_STRING),
+        options.get('variable_start_string', VARIABLE_START_STRING),
+        options.get('variable_end_string', VARIABLE_END_STRING),
+        options.get('comment_start_string', COMMENT_START_STRING),
+        options.get('comment_end_string', COMMENT_END_STRING),
+        options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
+        options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
+        getbool(options, 'trim_blocks', TRIM_BLOCKS),
+        NEWLINE_SEQUENCE, frozenset(extensions),
+        cache_size=0,
+        auto_reload=False
+    )
+
+    if getbool(options, 'newstyle_gettext'):
+        environment.newstyle_gettext = True
+
+    source = fileobj.read().decode(options.get('encoding', 'utf-8'))
+    try:
+        node = environment.parse(source)
+        tokens = list(environment.lex(environment.preprocess(source)))
+    except TemplateSyntaxError, e:
+        # skip templates with syntax errors
+        return
+
+    finder = _CommentFinder(tokens, comment_tags)
+    for lineno, func, message in extract_from_ast(node, keywords):
+        yield lineno, func, message, finder.find_comments(lineno)
+
+
+#: nicer import names
+i18n = InternationalizationExtension
+do = ExprStmtExtension
+loopcontrols = LoopControlExtension
+with_ = WithExtension
+autoescape = AutoEscapeExtension


[56/59] [abbrv] git commit: AMBARI-7152. Admin View: User is still present as group member after deleting.

Posted by nc...@apache.org.
AMBARI-7152. Admin View: User is still present as group member after deleting.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fcd8d1f7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fcd8d1f7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fcd8d1f7

Branch: refs/heads/branch-alerts-dev
Commit: fcd8d1f7ddfa3e136588d481b7fa9eeeb836e085
Parents: 301714a
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Thu Sep 4 13:03:16 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Thu Sep 4 13:03:56 2014 -0700

----------------------------------------------------------------------
 .../src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java    | 1 +
 .../src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java     | 1 +
 2 files changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fcd8d1f7/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
index b918454..a2caefa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
@@ -92,6 +92,7 @@ public class GroupDAO {
   @Transactional
   public void remove(GroupEntity group) {
     entityManagerProvider.get().remove(merge(group));
+    entityManagerProvider.get().getEntityManagerFactory().getCache().evictAll();
   }
 
   @Transactional

http://git-wip-us.apache.org/repos/asf/ambari/blob/fcd8d1f7/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
index 0aa7216..dcbd64c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
@@ -103,6 +103,7 @@ public class UserDAO {
   @Transactional
   public void remove(UserEntity user) {
     entityManagerProvider.get().remove(merge(user));
+    entityManagerProvider.get().getEntityManagerFactory().getCache().evictAll();
   }
 
   @Transactional