#!/usr/bin/env python
"""Generate performance diagnostics.

The purpose of this script is to generate performance diagnostics for
various jmespath expressions to be able to track the performance
over time.  The test files are data driven similar to the
compliance tests.
"""
import argparse
import time
import os
import json
import sys

from jmespath.parser import Parser


DIRECTORY = os.path.join(os.path.dirname(os.path.abspath(__file__)))
DEFAULT_NUM_LOOP = 100


def run_tests(tests):
    times = []
    for test in tests:
        given = test['given']
        expression = test['expression']
        parse_time = _parse_time(expression)
        search_time = _search_time(expression, given)
        sys.stdout.write(
            "parse_time: %.8fms, search_time: %.8fms" % (
            1000 * parse_time, 1000 * search_time))
        sys.stdout.write(" description: %s " % test['description'])
        sys.stdout.write("name: %s\n" % test['name'])


def _search_time(expression, given):
    p = Parser()
    parsed = p.parse(expression)
    best = float('inf')
    for i in range(DEFAULT_NUM_LOOP):
        start = time.time()
        parsed.search(given)
        end = time.time()
        total = end - start
        if total < best:
            best = total
    return best

def _parse_time(expression):
    best = float('inf')
    p = Parser()
    for i in range(DEFAULT_NUM_LOOP):
        p.purge()
        start = time.time()
        p.parse(expression)
        end = time.time()
        total = end - start
        if total < best:
            best = total
    return best

def load_tests(filename):
    loaded = []
    with open(filename) as f:
        data = json.load(f)
    if isinstance(data, list):
        for i, d in enumerate(data):
            _add_cases(d, loaded, '%s-%s' % (filename, i))
    else:
        _add_cases(data, loaded, filename)
    return loaded

def _add_cases(data, loaded, filename):
    for case in data['cases']:
        current = {'description': data.get('description', filename),
                   'given': data['given'],
                   'name': case.get('name', case['expression']),
                   'expression': case['expression'],
                   'result': case['result']}
        loaded.append(current)
    return loaded


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--directory', default=DIRECTORY)
    args = parser.parse_args()
    collected_tests = []
    for filename in os.listdir(args.directory):
        if filename.endswith('.json'):
            full_path = os.path.join(args.directory, filename)
            collected_tests.extend(load_tests(full_path))
    run_tests(collected_tests)


if __name__ == '__main__':
    main()

@@ -365,16 +365,59 @@
  Parser%0A
+from jmespath.lexer import LexerDefinition%0A
 %0A%0ADIRECT
@@ -630,24 +630,65 @@
 xpression'%5D%0A
+        lex_time = _lex_time(expression)%0A
         pars
@@ -813,16 +813,32 @@
        %22
+lex_time: %25.8f, 
 parse_ti
@@ -885,16 +885,37 @@
         
+     1000 * lex_time,
  1000 * 
@@ -1071,16 +1071,628 @@
 me'%5D)%0A%0A%0A
+def _lex_time(expression):%0A    import ply.lex%0A    definitions = LexerDefinition%0A    create_lexer = ply.lex.lex%0A    best = float('inf')%0A    for i in range(DEFAULT_NUM_LOOP):%0A        start = time.time()%0A        lexer = create_lexer(module=definitions(),%0A                             debug=False,%0A                             reflags=definitions.reflags)%0A        lexer.input(expression)%0A        while True:%0A            token = lexer.token()%0A            if token is None:%0A                break%0A        end = time.time()%0A        total = end - start%0A        if total %3C best:%0A            best = total%0A    return best%0A%0A%0A
 def _sea

Update perftest to measure lexing time