1#!/usr/bin/env python
2
3import os
4import pprint
5
6try:
7    from functools import reduce
8except ImportError:
9    # Assume we have reduce
10    pass
11
12from Cheetah import Parser
13from Cheetah import Compiler
14from Cheetah import Template
15
16class Analyzer(Parser.Parser):
17    def __init__(self, *args, **kwargs):
18        self.calls = {}
19        super(Analyzer, self).__init__(*args, **kwargs)
20
21    def eatDirective(self):
22        directive = self.matchDirective()
23        try:
24            self.calls[directive] += 1
25        except KeyError:
26            self.calls[directive] = 1
27        super(Analyzer, self).eatDirective()
28
29class AnalysisCompiler(Compiler.ModuleCompiler):
30    parserClass = Analyzer
31
32
33def analyze(source):
34    klass = Template.Template.compile(source, compilerClass=AnalysisCompiler)
35    return klass._CHEETAH_compilerInstance._parser.calls
36
37def main_file(f):
38    fd = open(f, 'r')
39    try:
40        print u'>>> Analyzing %s' % f
41        calls = analyze(fd.read())
42        return calls
43    finally:
44        fd.close()
45
46
47def _find_templates(directory, suffix):
48    for root, dirs, files in os.walk(directory):
49        for f in files:
50            if not f.endswith(suffix):
51                continue
52            yield root + os.path.sep + f
53
54def _analyze_templates(iterable):
55    for template in iterable:
56        yield main_file(template)
57
58def main_dir(opts):
59    results = _analyze_templates(_find_templates(opts.dir, opts.suffix))
60    totals = {}
61    for series in results:
62        if not series:
63            continue
64        for k, v in series.iteritems():
65            try:
66                totals[k] += v
67            except KeyError:
68                totals[k] = v
69    return totals
70
71
72def main():
73    from optparse import OptionParser
74    op = OptionParser()
75    op.add_option('-f', '--file', dest='file', default=None,
76            help='Specify a single file to analyze')
77    op.add_option('-d', '--dir', dest='dir', default=None,
78            help='Specify a directory of templates to analyze')
79    op.add_option('--suffix', default='tmpl', dest='suffix',
80            help='Specify a custom template file suffix for the -d option (default: "tmpl")')
81    opts, args = op.parse_args()
82
83    if not opts.file and not opts.dir:
84        op.print_help()
85        return
86
87    results = None
88    if opts.file:
89        results = main_file(opts.file)
90    if opts.dir:
91        results = main_dir(opts)
92
93    pprint.pprint(results)
94
95
96if __name__ == '__main__':
97    main()
98
99