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