Return-Path: X-Original-To: apmail-ambari-commits-archive@www.apache.org Delivered-To: apmail-ambari-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B24D01793B for ; Thu, 16 Oct 2014 20:11:27 +0000 (UTC) Received: (qmail 39444 invoked by uid 500); 16 Oct 2014 20:11:27 -0000 Delivered-To: apmail-ambari-commits-archive@ambari.apache.org Received: (qmail 39362 invoked by uid 500); 16 Oct 2014 20:11:27 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 38831 invoked by uid 99); 16 Oct 2014 20:11:27 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 16 Oct 2014 20:11:27 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id E720C9D2266; Thu, 16 Oct 2014 20:11:26 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: yusaku@apache.org To: commits@ambari.apache.org Date: Thu, 16 Oct 2014 20:11:53 -0000 Message-Id: <359f1f032a364b2297bfccfb31cc5c3c@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [29/51] [partial] AMBARI-7718. Rebase branch-windows-dev against trunk. (Jayush Luniya and Florian Barca via yusaku) http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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("""\ + + + + ${page_title|e} + + +
+

${page_title|e}

+
+ +
+ + % for row in table + + % for cell in row + + % endfor + + % endfor +
${cell}
+
+ +\ +""") + +def test_jinja(): + jinja_template.render(context) + +try: + from tornado.template import Template +except ImportError: + test_tornado = None +else: + tornado_template = Template("""\ + + + + {{ page_title }} + + +
+

{{ page_title }}

+
+ +
+ + {% for row in table %} + + {% for cell in row %} + + {% end %} + + {% end %} +
{{ cell }}
+
+ +\ +""") + + 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("""\ + + + + {{ page_title }} + + +
+

{{ page_title }}

+
+ +
+ + {% for row in table %} + + {% for cell in row %} + + {% endfor %} + + {% endfor %} +
{{ cell }}
+
+ +\ +""") + + 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("""\ + + + + ${page_title|h} + + +
+

${page_title|h}

+
+ +
+ + % for row in table: + + % for cell in row: + + % endfor + + % endfor +
${cell}
+
+ +\ +""") + + def test_mako(): + mako_template.render(**context) + +try: + from genshi.template import MarkupTemplate as GenshiTemplate +except ImportError: + test_genshi = None +else: + genshi_template = GenshiTemplate("""\ + + + ${page_title} + + +
+

${page_title}

+
+ +
+ + + + +
${cell}
+
+ +\ +""") + + 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 + + + + $cgi.escape($page_title) + + +
+

$cgi.escape($page_title)

+
+ +
+ + #for $row in $table: + + #for $cell in $row: + + #end for + + #end for +
$cell
+
+ +\ +""", 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("""\ + + + + ${page_title} + + +
+

${page_title}

+
+ +
+ + + + + + + + +
#{cell}
+
+ +\ +""") + + 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("""\ + + + + $cgi.escape($page_title) + + +
+

$cgi.escape($page_title)

+
+ +
+ + #for $row in $table + + #for $cell in $row + + #end for + + #end for +
$cell
+
+ +\ +""", '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("""\ + + + Page Title + + +
+

Page Title

+
+ +
+ + + + +
cell
+
+ +\ +""") + 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("""\ + + + ${page_title} + + +
+

${page_title}

+
+ +
+ + + + +
${row[cell]}
+
+ +\ +""", 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' % 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/9213dcca/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) + ${x} +% endmacro + + + + ${page_title|e} + + +
+

${page_title|e}

+
+
+ + % for row in table + + % for cell in row + + % endfor + + % endfor +
${testmacro(cell)}
+
+ +\ +""" +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/9213dcca/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 @@ +
{{ body }}
http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ + http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ + http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 %} +
+

{{ article.title }}

+

written by {{ article.user.username }} on {{ article.pub_date|dateformat }}

+
{{ article.body|safe }}
+
+ {% endif %} + {% endfor %} + {% form %} +
+
Name
+
{% input_field 'name' %}
+
E-Mail
+
{% input_field 'email' %}
+
URL
+
{% input_field 'url' %}
+
Comment
+
{% textarea 'comment' %}
+
Captcha
+
{% input_field 'captcha' %}
+
+ {% input_field '' 'submit' 'Submit' %} + {% input_field 'cancel' 'submit' 'Cancel' %} + {% endform %} +{% endblock %} http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ + + + + {% block page_title %}{% endblock %} | RealWorld Benchmark + + + +
+
+

RealWorld Benchmark

+

+ A less stupid benchmark for Mako and Jinja2 to get an impression how + code changes affect runtime performance. +

+
+ +
+ {% block body %}{% endblock %} +
+ +
+ + http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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/9213dcca/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 @@ +
+ + + + + + + + + +
http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ + + + + + Index Page + +
+ +

${article.title}

+

written by ${article.user.username} on ${dateformat(article.pub_date)}

+
${Markup(article.body)}
+
+
+ +
+
+
Name
+
${input_field('name')}
+
E-Mail
+
${input_field('email')}
+
URL
+
${input_field('url')}
+
Comment
+
${textarea('comment')}
+
Captcha
+
${input_field('captcha')}
+
+ ${input_field(type='submit', value='Submit')} + ${input_field(name='cancel', type='submit', value='Cancel')} +
+ + http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ + + + + ${select('title/text()')} | RealWorld Benchmark + + + + + +
+
+

RealWorld Benchmark

+

+ A less stupid benchmark for Mako and Jinja2 to get an impression how + code changes affect runtime performance. +

+
+ +
+ ${select('*|text()')} +
+ +
+ +
+ http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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') -%} + +{%- endmacro %} + +{% macro textarea(name, value='', rows=10, cols=40) -%} + +{%- endmacro %} + +{% macro form(action='', method='post') -%} +
{{ caller() }}
+{%- endmacro %} http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 %} +
+

{{ article.title|e }}

+

written by {{ article.user.username|e }} on {{ article.pub_date|dateformat }}

+
{{ article.body }}
+
+ {%- endfor %} + {%- call form() %} +
+
Name
+
{{ input_field('name') }}
+
E-Mail
+
{{ input_field('email') }}
+
URL
+
{{ input_field('url') }}
+
Comment
+
{{ textarea('comment') }}
+
Captcha
+
{{ input_field('captcha') }}
+
+ {{ 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/9213dcca/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 @@ + + + + {% block page_title %}{% endblock %} | RealWorld Benchmark + + + +
+
+

RealWorld Benchmark

+

+ A less stupid benchmark for Mako and Jinja2 to get an impression how + code changes affect runtime performance. +

+
+ +
+ {% block body %}{% endblock %} +
+ +
+ + http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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')"> + + + +<%def name="textarea(name, value='', rows=10, cols=40)"> + + + +<%def name="form(action='', method='post')"> +
${caller.body()}
+ http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 +% for article in articles: + <% if not article.published: continue %> +
+

${article.title|h}

+

written by ${article.user.username|h} on ${dateformat(article.pub_date)}

+
${article.body}
+
+% endfor +<%call expr="form()"> +
+
Name
+
${input_field('name')}
+
E-Mail
+
${input_field('email')}
+
URL
+
${input_field('url')}
+
Comment
+
${textarea('comment')}
+
Captcha
+
${input_field('captcha')}
+
+ ${input_field(type='submit', value='Submit')} + ${input_field(name='cancel', type='submit', value='Cancel')} + http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ + + + + ${self.page_title()} | RealWorld Benchmark + + + +
+
+

RealWorld Benchmark

+

+ A less stupid benchmark for Mako and Jinja2 to get an impression how + code changes affect runtime performance. +

+
+ +
+ ${self.body()} +
+ +
+ + +<%def name="page_title()"> http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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' % 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/9213dcca/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 +" 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 :p:h/jinja.vim + so :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/9213dcca/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 +" 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 /\/ 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 + else + command -nargs=+ HiLink hi def link + 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/9213dcca/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..9f15266 --- /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 = '' + 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/9213dcca/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/9213dcca/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 %} +
  • {{ item }}
  • + {% 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 %} + + {% endwith %} + +
    {% debug %}
    + + {% 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 %} + +

    {% trans "This is the title." %}

    + + {% regroup people by gender as grouped %} +{% endblock %} http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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 @@ +{% block title %}{% endblock %} +
    + {% block page-body %}{% endblock %} +
    http://git-wip-us.apache.org/repos/asf/ambari/blob/9213dcca/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/9213dcca/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/9213dcca/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:: + +

    _(Welcome)

    +

    _(This is a paragraph)

    + + 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/9213dcca/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()