root/pkgcore-checks/pkgcore_checks/reporters.py @ ferringb%2540gmail.com-20080624174036-q45fk4fxguj9kjlv

Revision ferringb%2540gmail.com-20080624174036-q45fk4fxguj9kjlv, 6.3 kB (checked in by Brian Harring <ferringb@…>, 7 months ago)

punt trailing whitespace

Line 
1# Copyright: 2006 Brian Harring <ferringb@gmail.com>
2# Copyright: 2006 Marien Zwart <marienz@gentoo.org>
3# License: GPL2
4
5
6"""Basic reporters and reporter factories."""
7
8from pkgcore_checks import base
9from pkgcore.config import configurable
10from snakeoil import formatters
11from snakeoil.demandload import demandload
12
13demandload(globals(),
14    'pkgcore_checks:errors',
15    'snakeoil:currying',
16    'snakeoil:pickling',
17    'snakeoil:xml',
18)
19
20
21class StrReporter(base.Reporter):
22
23    """
24    Simple string reporter, pcheck-0.1 behaviour. example:
25    sys-apps/portage-2.1-r2: sys-apps/portage-2.1-r2.ebuild has whitespace in indentation on line 169
26    sys-apps/portage-2.1-r2: rdepends  ppc-macos: unsolvable default-darwin/macos/10.4, solutions: [ >=app-misc/pax-utils-0.1.13 ]
27    sys-apps/portage-2.1-r2: no change in 75 days, keywords [ ~x86-fbsd ]
28    """
29
30    # simple reporter; fallback default
31    priority = 0
32
33    def __init__(self, out):
34        """Initialize.
35        @type out: L{snakeoil.formatters.Formatter}.
36        """
37        base.Reporter.__init__(self)
38        self.out = out
39        self.first_report = True
40
41    def add_report(self, result):
42        if self.first_report:
43            self.out.write()
44            self.first_report = False
45        if result.threshold == base.versioned_feed:
46            self.out.write("%s/%s-%s: %s" % (result.category, result.package,
47                result.version, result.short_desc))
48        elif result.threshold == base.package_feed:
49            self.out.write("%s/%s: %s" % (result.category, result.package,
50                result.short_desc))
51        elif result.threshold == base.category_feed:
52            self.out.write("%s: %s" % (result.category, result.short_desc))
53        else:
54            self.out.write(result.short_desc)
55
56    def finish(self):
57        if not self.first_report:
58            self.out.write()
59
60
61class FancyReporter(base.Reporter):
62
63    """
64    groupped colored output, example:
65
66    sys-apps/portage
67      WrongIndentFound: sys-apps/portage-2.1-r2.ebuild has whitespace in indentation on line 169
68      NonsolvableDeps: sys-apps/portage-2.1-r2: rdepends  ppc-macos: unsolvable default-darwin/macos/10.4, solutions: [ >=app-misc/pax-utils-0.1.13 ]
69      StaleUnstableKeyword: sys-apps/portage-2.1-r2: no change in 75 days, keywords [ ~x86-fbsd ]
70    """
71
72    # default report, akin to repoman
73    priority = 1
74
75    def __init__(self, out):
76        """Initialize.
77
78        @type out: L{snakeoil.formatters.Formatter}.
79        """
80        base.Reporter.__init__(self)
81        self.out = out
82        self.key = None
83
84    def add_report(self, result):
85        cat = getattr(result, 'category', None)
86        pkg = getattr(result, 'package', None)
87        if cat is None or pkg is None:
88            key = 'unknown'
89        else:
90            key = '%s/%s' % (cat, pkg)
91        if key != self.key:
92            self.out.write()
93            self.out.write(self.out.bold, key)
94            self.key = key
95        self.out.first_prefix.append('  ')
96        self.out.later_prefix.append('    ')
97        s = ''
98        if result.threshold == base.versioned_feed:
99            s = "version %s: " % result.version
100        self.out.write(
101            self.out.fg('yellow'), result.__class__.__name__, self.out.reset,
102            ': ', s, result.short_desc)
103        self.out.first_prefix.pop()
104        self.out.later_prefix.pop()
105
106
107class XmlReporter(base.Reporter):
108
109    """
110    dump an xml feed of reports
111    """
112
113    # xml report, shouldn't be used but in worst case.
114    priority = -1000
115
116    repo_template = "<result><msg>%s</msg></result>"
117    cat_template = "<result><category>%(category)s</category><msg>%(msg)s</msg></result>"
118    pkg_template = ("<result><category>%(category)s</category>"
119        "<package>%(package)s</package><msg>%(msg)s</msg></result>")
120    ver_template = ("<result><category>%(category)s</category>"
121        "<package>%(package)s</package><version>%(version)s</version>"
122        "<msg>%(msg)s</msg></result>")
123
124    threshold_map = {base.repository_feed:repo_template,
125        base.category_feed:cat_template,
126        base.package_feed:pkg_template,
127        base.versioned_feed:ver_template,
128        base.ebuild_feed:ver_template
129    }
130
131    def __init__(self, out):
132        """Initialize.
133
134        @type out: L{snakeoil.formatters.Formatter}.
135        """
136        base.Reporter.__init__(self)
137        self.out = out
138
139    def start(self):
140        self.out.write('<checks>')
141
142    def add_report(self, result):
143        d = dict((k, getattr(result, k, '')) for k in
144            ("category", "package", "version"))
145        d["msg"] = xml.escape(result.short_desc)
146        self.out.write(self.threshold_map[result.threshold] % d)
147
148    def finish(self):
149        self.out.write('</checks>')
150
151
152class MultiplexReporter(base.Reporter):
153
154    def __init__(self, *reporters):
155        if len(reporters) < 2:
156            raise ValueError("need at least two reporters")
157        base.Reporter.__init__(self)
158        self.reporters = tuple(reporters)
159
160    def start(self):
161        for x in self.reporters:
162            x.start()
163
164    def add_report(self, result):
165        for x in self.reporters:
166            x.add_report(result)
167
168    def finish(self):
169        for x in self.reporters:
170            x.finish()
171
172
173def make_configurable_reporter_factory(klass):
174    @configurable({'dest': 'str'}, typename='pcheck_reporter_factory')
175    def configurable_reporter_factory(dest=None):
176        if dest is None:
177            return klass
178        def reporter_factory(out):
179            try:
180                f = open(dest, 'w')
181            except (IOError, OSError), e:
182                raise errors.ReporterInitError(
183                    'Cannot write to %r (%s)' % (dest, e))
184            return klass(formatters.PlainTextFormatter(f))
185        return reporter_factory
186    return configurable_reporter_factory
187
188xml_reporter = make_configurable_reporter_factory(XmlReporter)
189xml_reporter.__name__ = 'xml_reporter'
190plain_reporter = make_configurable_reporter_factory(StrReporter)
191plain_reporter.__name__ = 'plain_reporter'
192fancy_reporter = make_configurable_reporter_factory(FancyReporter)
193fancy_reporter.__name__ = 'fancy_reporter'
194
195@configurable({'reporters': 'refs:pcheck_reporter_factory'},
196              typename='pcheck_reporter_factory')
197def multiplex_reporter(reporters):
198    def make_multiplex_reporter(out):
199        return MultiplexReporter(*list(factory(out) for factory in reporters))
200    return make_multiplex_reporter
Note: See TracBrowser for help on using the browser.