# 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 io import StringIO import sys import timeit __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)] 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 lookup = TemplateLookup(directories=[dirname], filesystem_checks=False) template = lookup.get_template("template.html") def render(): return template.render(title=TITLE, user=USER, list_items=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=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": 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)