]> scripts.mit.edu Git - wizard.git/blob - wizard/command/summary.py
Refactor summary to be more function-oriented.
[wizard.git] / wizard / command / summary.py
1 import logging
2 import optparse
3 import math
4 import os
5
6 from wizard import deploy
7 from wizard.command import _base
8
9 def main(argv, global_options):
10     options, show = parse_args(argv)
11     if not show: show = deploy.applications.keys()
12     options.dispatch(parse_install_lines(show, options, global_options))
13
14 def parse_args(argv):
15     usage = """usage: %prog summary [ARGS] APPS
16
17 Scans all of the collected data from parallel-find.pl, and
18 determines version histograms for our applications.  You may
19 optionally pass application parameters to filter the installs.
20
21 Examples:
22     %prog summary
23         Basic usage
24     %prog summary mediawiki
25         Displays only MediaWiki statistics"""
26     parser = _base.WizardOptionParser(usage)
27     def addDispatch(flag, function, type, help):
28         parser.add_option(flag, action="callback",
29             callback=make_callback(function), type=type, help=help)
30     addDispatch("--count-exists", summary_count_exists, "string",
31             "Count deployments that contain a file")
32     addDispatch("--list", summary_list, None,
33             "Print locations of deployments that match APPS")
34     parser.add_option("--warn-unrecognized", dest="warn_unrecognized", action="store_true",
35             default=False, help="Emit warnings when unrecognized applications are found")
36     options, show = parser.parse_all(argv)
37     if not hasattr(options, "dispatch"):
38         # default
39         options.dispatch = summary_version
40     return options, show
41
42 def make_callback(f):
43     def callback(option, opt_str, value, parser):
44         if hasattr(parser.values, "dispatch"):
45             # maybe make this more flexible
46             raise optparse.OptionValueError("Cannot use multiple summary modes")
47         parser.values.dispatch = lambda x: f(x, value)
48     return callback
49
50 def parse_install_lines(show, options, global_options):
51     show = frozenset(show)
52     for line in deploy.getInstallLines(global_options):
53         # construction
54         try:
55             d = deploy.Deployment.parse(line)
56             name = d.getApplication().name
57         except deploy.NoSuchApplication:
58             if options.warn_unrecognized:
59                 logging.warning("Unrecognized application with '%s'" % line.rstrip())
60             continue
61         except deploy.Error:
62             logging.warning("Error with '%s'" % line.rstrip())
63             continue
64         # filter
65         if name + "-" + str(d.getVersion()) in show or name in show:
66             pass
67         else:
68             continue
69         # yield
70         yield d
71
72 def print_summary(show, errors, unrecognized):
73     for app in deploy.applications.values():
74         if app.name not in show: continue
75         print app.report()
76         print
77     print "With %d errors and %d unrecognized applications" % (errors, unrecognized)
78
79 def summary_list(deploys, value):
80     for d in deploys:
81         print d.location
82
83 def summary_version(deploys, value):
84     HISTOGRAM_WIDTH = 30
85     show = set()
86     version_counts = {}
87     application_counts = {}
88     for d in deploys:
89         version = d.getAppVersion()
90         version_counts.setdefault(version, 0)
91         application_counts.setdefault(version.application, 0)
92         version_counts[version] += 1
93         application_counts[version.application] += 1
94         show.add(version.application)
95     if not show:
96         print "No applications found"
97     for application in show:
98         print "%-16s %3d installs" % (application.name, application_counts[application])
99         vmax = max(version_counts[x] for x in application.versions.values())
100         for version in sorted(application.versions.values()):
101             v = version_counts[version]
102             graph = '+' * int(math.ceil(float(v)/vmax * HISTOGRAM_WIDTH))
103             print "    %-12s %3d  %s" % (version.version, v, graph)
104         print
105
106 def summary_count_exists(deploys, value):
107     for d in deploys:
108         if os.path.exists(d.location + "/" + value):
109             print d.location
110