| # basic.py - basic benchmarks adapted from Genshi |
| # Copyright (C) 2006 Edgewall Software |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. 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. |
| # 3. The name of the author may not be used to endorse or promote |
| # products derived from this software without specific prior |
| # written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. |
| |
| from cgi import escape |
| import os |
| try: |
| from StringIO import StringIO |
| except ImportError: |
| from io import StringIO |
| import sys |
| import timeit |
| |
| def u(stringlit): |
| if sys.version_info >= (3,): |
| return stringlit |
| else: |
| return stringlit.decode('latin1') |
| |
| __all__ = ['mako', 'mako_inheritance', 'jinja2', 'jinja2_inheritance', |
| 'cheetah', 'django', 'myghty', 'genshi', 'kid'] |
| |
| # Templates content and constants |
| TITLE = 'Just a test' |
| USER = 'joe' |
| ITEMS = ['Number %d' % num for num in range(1, 15)] |
| U_ITEMS = [u(item) for item in ITEMS] |
| |
| def genshi(dirname, verbose=False): |
| from genshi.template import TemplateLoader |
| loader = TemplateLoader([dirname], auto_reload=False) |
| template = loader.load('template.html') |
| def render(): |
| data = dict(title=TITLE, user=USER, items=ITEMS) |
| return template.generate(**data).render('xhtml') |
| |
| if verbose: |
| print(render()) |
| return render |
| |
| def myghty(dirname, verbose=False): |
| from myghty import interp |
| interpreter = interp.Interpreter(component_root=dirname) |
| def render(): |
| data = dict(title=TITLE, user=USER, items=ITEMS) |
| buffer = StringIO() |
| interpreter.execute("template.myt", request_args=data, out_buffer=buffer) |
| return buffer.getvalue() |
| if verbose: |
| print(render()) |
| return render |
| |
| def mako(dirname, verbose=False): |
| from mako.template import Template |
| from mako.lookup import TemplateLookup |
| disable_unicode = (sys.version_info < (3,)) |
| lookup = TemplateLookup(directories=[dirname], filesystem_checks=False, disable_unicode=disable_unicode) |
| template = lookup.get_template('template.html') |
| def render(): |
| return template.render(title=TITLE, user=USER, list_items=U_ITEMS) |
| if verbose: |
| print(template.code + " " + render()) |
| return render |
| mako_inheritance = mako |
| |
| def jinja2(dirname, verbose=False): |
| from jinja2 import Environment, FileSystemLoader |
| env = Environment(loader=FileSystemLoader(dirname)) |
| template = env.get_template('template.html') |
| def render(): |
| return template.render(title=TITLE, user=USER, list_items=U_ITEMS) |
| if verbose: |
| print(render()) |
| return render |
| jinja2_inheritance = jinja2 |
| |
| def cheetah(dirname, verbose=False): |
| from Cheetah.Template import Template |
| filename = os.path.join(dirname, 'template.tmpl') |
| template = Template(file=filename) |
| def render(): |
| template.__dict__.update({'title': TITLE, 'user': USER, |
| 'list_items': U_ITEMS}) |
| return template.respond() |
| |
| if verbose: |
| print(dir(template)) |
| print(template.generatedModuleCode()) |
| print(render()) |
| return render |
| |
| def django(dirname, verbose=False): |
| from django.conf import settings |
| settings.configure(TEMPLATE_DIRS=[os.path.join(dirname, 'templates')]) |
| from django import template, templatetags |
| from django.template import loader |
| templatetags.__path__.append(os.path.join(dirname, 'templatetags')) |
| tmpl = loader.get_template('template.html') |
| |
| def render(): |
| data = {'title': TITLE, 'user': USER, 'items': ITEMS} |
| return tmpl.render(template.Context(data)) |
| |
| if verbose: |
| print(render()) |
| return render |
| |
| def kid(dirname, verbose=False): |
| import kid |
| kid.path = kid.TemplatePath([dirname]) |
| template = kid.Template(file='template.kid') |
| def render(): |
| template = kid.Template(file='template.kid', |
| title=TITLE, user=USER, items=ITEMS) |
| return template.serialize(output='xhtml') |
| |
| if verbose: |
| print(render()) |
| return render |
| |
| |
| def run(engines, number=2000, verbose=False): |
| basepath = os.path.abspath(os.path.dirname(__file__)) |
| for engine in engines: |
| dirname = os.path.join(basepath, engine) |
| if verbose: |
| print('%s:' % engine.capitalize()) |
| print('--------------------------------------------------------') |
| else: |
| sys.stdout.write('%s:' % engine.capitalize()) |
| t = timeit.Timer(setup='from __main__ import %s; render = %s(r"%s", %s)' |
| % (engine, engine, dirname, verbose), |
| stmt='render()') |
| |
| time = t.timeit(number=number) / number |
| if verbose: |
| print('--------------------------------------------------------') |
| print('%.2f ms' % (1000 * time)) |
| if verbose: |
| print('--------------------------------------------------------') |
| |
| |
| if __name__ == '__main__': |
| engines = [arg for arg in sys.argv[1:] if arg[0] != '-'] |
| if not engines: |
| engines = __all__ |
| |
| verbose = '-v' in sys.argv |
| |
| if '-p' in sys.argv: |
| try: |
| import hotshot, hotshot.stats |
| prof = hotshot.Profile("template.prof") |
| benchtime = prof.runcall(run, engines, number=100, verbose=verbose) |
| stats = hotshot.stats.load("template.prof") |
| except ImportError: |
| import cProfile, pstats |
| stmt = "run(%r, number=%r, verbose=%r)" % (engines, 1000, verbose) |
| cProfile.runctx(stmt, globals(), {}, "template.prof") |
| stats = pstats.Stats("template.prof") |
| stats.strip_dirs() |
| stats.sort_stats('time', 'calls') |
| stats.print_stats() |
| else: |
| run(engines, verbose=verbose) |