# 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
from StringIO import StringIO
import sys
import timeit

__all__ = ['mako', 'mako_inheritance', 'cheetah', 'django', 'myghty', 'genshi', 'kid']

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='Just a test', user='joe',
                    items=['Number %d' % num for num in range(1, 15)])
        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='Just a test', user='joe',
                    items=['Number %d' % num for num in range(1, 15)])
        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, disable_unicode=True)
    template = lookup.get_template('template.html')
    def render():
        return template.render(title="Just a test", user="joe", list_items=[u'Number %d' % num for num in range(1,15)])
    if verbose:
        print template.code, render()
    return render
mako_inheritance = mako

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': 'Just a test', 'user': 'joe',
                                  'list_items': [u'Number %d' % num for num in range(1, 15)]})
        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': 'Just a test', 'user': 'joe',
                'items': ['Number %d' % num for num in range(1, 15)]}
        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='Just a test', user='joe',
                                items=['Number %d' % num for num in range(1, 15)])
        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:
            print '%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:
        import hotshot, hotshot.stats
        prof = hotshot.Profile("template.prof")
        benchtime = prof.runcall(run, engines, number=100, verbose=verbose)
        stats = hotshot.stats.load("template.prof")
        stats.strip_dirs()
        stats.sort_stats('time', 'calls')
        stats.print_stats()
    else:
        run(engines, verbose=verbose)
