1# Copyright 2015 Anton Shestakov
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7
8from tests.helper import ListWithUnused as L
9from tests.plugin import PluginTestCase
10from quodlibet.util.string.titlecase import human_title
11
12
13class TPluginStyle(PluginTestCase):
14    def conclude(self, fails):
15        def format_msg(f):
16            return "%s: '%s' plugin (%s)" % (f[1], f[0].name, f[0].cls)
17        if not fails:
18            return
19        grouped = {}
20        for f in fails:
21            grouped.setdefault(f[2], []).append(f)
22        lines = []
23        for reason in grouped:
24            lines.append('== ' + reason + ' ==')
25            for f in grouped[reason]:
26                plugin, string = f[:2]
27                pclass = plugin.cls.__name__
28                ppath = plugin.cls.__module__.rpartition('.plugins.')[2]
29                lines.append("%s.%s: %r" % (ppath, pclass, string))
30        self.fail("One or more plugins did not pass:\n" + '\n'.join(lines))
31
32    def test_plugin_name(self):
33        REASON_ABSENT = "plugin should have PLUGIN_NAME"
34        REASON_CASE = "PLUGIN_NAME should be in Title Case"
35
36        ok_names = L(
37            'Last.fm Cover Source', 'Last.fm Sync', 'Send to iFP',
38            'This is a test')
39        fails = []
40
41        for pid, plugin in self.plugins.items():
42            if not hasattr(plugin.cls, 'PLUGIN_NAME'):
43                fails.append((plugin, None, REASON_ABSENT))
44                continue
45            name = plugin.cls.PLUGIN_NAME
46            if name != human_title(name):
47                if name not in ok_names:
48                    fails.append((plugin, name, REASON_CASE))
49
50        ok_names.check_unused()
51        self.conclude(fails)
52
53    def test_plugin_desc(self):
54        REASON_ABSENT = "plugin should have PLUGIN_DESC"
55        REASON_DOT = "PLUGIN_DESC should be a full sentence and end with a '.'"
56
57        skip_plugins = L('pickle_plugin')
58        fails = []
59
60        for pid, plugin in self.plugins.items():
61            if pid in skip_plugins:
62                continue
63            if not hasattr(plugin.cls, 'PLUGIN_DESC'):
64                fails.append((plugin, None, REASON_ABSENT))
65                continue
66            desc = plugin.cls.PLUGIN_DESC
67            if not desc.endswith('.'):
68                fails.append((plugin, desc, REASON_DOT))
69
70        skip_plugins.check_unused()
71        self.conclude(fails)
72