1# basic.py - basic benchmarks adapted from Genshi 2# Copyright (C) 2006 Edgewall Software 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in 13# the documentation and/or other materials provided with the 14# distribution. 15# 3. The name of the author may not be used to endorse or promote 16# products derived from this software without specific prior 17# written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 20# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 27# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 29# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31from io import StringIO 32import sys 33import timeit 34 35 36__all__ = [ 37 "mako", 38 "mako_inheritance", 39 "jinja2", 40 "jinja2_inheritance", 41 "cheetah", 42 "django", 43 "myghty", 44 "genshi", 45 "kid", 46] 47 48# Templates content and constants 49TITLE = "Just a test" 50USER = "joe" 51ITEMS = ["Number %d" % num for num in range(1, 15)] 52 53 54def genshi(dirname, verbose=False): 55 from genshi.template import TemplateLoader 56 57 loader = TemplateLoader([dirname], auto_reload=False) 58 template = loader.load("template.html") 59 60 def render(): 61 data = dict(title=TITLE, user=USER, items=ITEMS) 62 return template.generate(**data).render("xhtml") 63 64 if verbose: 65 print(render()) 66 return render 67 68 69def myghty(dirname, verbose=False): 70 from myghty import interp 71 72 interpreter = interp.Interpreter(component_root=dirname) 73 74 def render(): 75 data = dict(title=TITLE, user=USER, items=ITEMS) 76 buffer = StringIO() 77 interpreter.execute( 78 "template.myt", request_args=data, out_buffer=buffer 79 ) 80 return buffer.getvalue() 81 82 if verbose: 83 print(render()) 84 return render 85 86 87def mako(dirname, verbose=False): 88 from mako.template import Template 89 from mako.lookup import TemplateLookup 90 91 lookup = TemplateLookup(directories=[dirname], filesystem_checks=False) 92 template = lookup.get_template("template.html") 93 94 def render(): 95 return template.render(title=TITLE, user=USER, list_items=ITEMS) 96 97 if verbose: 98 print(template.code + " " + render()) 99 return render 100 101 102mako_inheritance = mako 103 104 105def jinja2(dirname, verbose=False): 106 from jinja2 import Environment, FileSystemLoader 107 108 env = Environment(loader=FileSystemLoader(dirname)) 109 template = env.get_template("template.html") 110 111 def render(): 112 return template.render(title=TITLE, user=USER, list_items=ITEMS) 113 114 if verbose: 115 print(render()) 116 return render 117 118 119jinja2_inheritance = jinja2 120 121 122def cheetah(dirname, verbose=False): 123 from Cheetah.Template import Template 124 125 filename = os.path.join(dirname, "template.tmpl") 126 template = Template(file=filename) 127 128 def render(): 129 template.__dict__.update( 130 {"title": TITLE, "user": USER, "list_items": ITEMS} 131 ) 132 return template.respond() 133 134 if verbose: 135 print(dir(template)) 136 print(template.generatedModuleCode()) 137 print(render()) 138 return render 139 140 141def django(dirname, verbose=False): 142 from django.conf import settings 143 144 settings.configure(TEMPLATE_DIRS=[os.path.join(dirname, "templates")]) 145 from django import template, templatetags 146 from django.template import loader 147 148 templatetags.__path__.append(os.path.join(dirname, "templatetags")) 149 tmpl = loader.get_template("template.html") 150 151 def render(): 152 data = {"title": TITLE, "user": USER, "items": ITEMS} 153 return tmpl.render(template.Context(data)) 154 155 if verbose: 156 print(render()) 157 return render 158 159 160def kid(dirname, verbose=False): 161 import kid 162 163 kid.path = kid.TemplatePath([dirname]) 164 template = kid.Template(file="template.kid") 165 166 def render(): 167 template = kid.Template( 168 file="template.kid", title=TITLE, user=USER, items=ITEMS 169 ) 170 return template.serialize(output="xhtml") 171 172 if verbose: 173 print(render()) 174 return render 175 176 177def run(engines, number=2000, verbose=False): 178 basepath = os.path.abspath(os.path.dirname(__file__)) 179 for engine in engines: 180 dirname = os.path.join(basepath, engine) 181 if verbose: 182 print("%s:" % engine.capitalize()) 183 print("--------------------------------------------------------") 184 else: 185 sys.stdout.write("%s:" % engine.capitalize()) 186 t = timeit.Timer( 187 setup='from __main__ import %s; render = %s(r"%s", %s)' 188 % (engine, engine, dirname, verbose), 189 stmt="render()", 190 ) 191 192 time = t.timeit(number=number) / number 193 if verbose: 194 print("--------------------------------------------------------") 195 print("%.2f ms" % (1000 * time)) 196 if verbose: 197 print("--------------------------------------------------------") 198 199 200if __name__ == "__main__": 201 engines = [arg for arg in sys.argv[1:] if arg[0] != "-"] 202 if not engines: 203 engines = __all__ 204 205 verbose = "-v" in sys.argv 206 207 if "-p" in sys.argv: 208 try: 209 import hotshot, hotshot.stats 210 211 prof = hotshot.Profile("template.prof") 212 benchtime = prof.runcall(run, engines, number=100, verbose=verbose) 213 stats = hotshot.stats.load("template.prof") 214 except ImportError: 215 import cProfile, pstats 216 217 stmt = "run(%r, number=%r, verbose=%r)" % (engines, 1000, verbose) 218 cProfile.runctx(stmt, globals(), {}, "template.prof") 219 stats = pstats.Stats("template.prof") 220 stats.strip_dirs() 221 stats.sort_stats("time", "calls") 222 stats.print_stats() 223 else: 224 run(engines, verbose=verbose) 225