1from pytest import File, Item
2
3from pytest_translations.config import MARKER_NAME
4from pytest_translations.po_spelling import PoSpellCheckingItem
5from pytest_translations.utils import TranslationException, open_po_file, msgfmt
6
7
8class PoFile(File):
9    def __init__(self, path, parent):
10        super(PoFile, self).__init__(path, parent)
11
12        if hasattr(self, 'add_marker'):
13            self.add_marker(MARKER_NAME)
14        else:
15            self.keywords[MARKER_NAME] = True
16
17    def collect(self):
18        yield PoUntranslatedItem(
19            self.name,
20            self,
21        )
22        yield PoFuzzyItem(
23            self.name,
24            self,
25        )
26        yield PoObsoleteItem(
27            self.name,
28            self,
29        )
30        try:
31            parsed = open_po_file(self.fspath)
32        except TranslationException:
33            # if the PO file is invalid, we can't do spellchecking.
34            # the other tests will fail then, but this here is the collection phase.
35            pass
36        else:
37            language = parsed.metadata.get('Language', '')
38            for line in parsed.translated_entries():
39                yield PoSpellCheckingItem(
40                    line,
41                    language,
42                    self.name,
43                    self,
44                )
45
46
47class PoBaseItem(Item):
48    def __init__(self, name, parent):
49        super(PoBaseItem, self).__init__(name, parent)
50        self.add_marker(MARKER_NAME)
51
52    def repr_failure(self, excinfo):
53        if isinstance(excinfo.value, TranslationException):
54            msg, wrong = excinfo.value.args
55
56            msg += "\n{0}".format(self.fspath)
57
58            msg += '\n' + '\n'.join(
59                msgfmt(i)
60                for i in wrong
61            )
62
63            return msg
64
65        else:
66            return super(PoBaseItem, self).repr_failure(excinfo)
67
68
69class PoUntranslatedItem(PoBaseItem):
70    def runtest(self):
71        parsed = open_po_file(self.fspath)
72
73        untranslated = parsed.untranslated_entries()
74
75        if not untranslated:
76            return
77
78        raise TranslationException(
79            'found untranslated entries in file.',
80            untranslated,
81        )
82
83    def reportinfo(self):
84        return (self.fspath, -1, "po-untranslated")
85
86
87class PoObsoleteItem(PoBaseItem):
88    def runtest(self):
89        parsed = open_po_file(self.fspath)
90
91        obsolete = parsed.obsolete_entries()
92
93        if not obsolete:
94            return
95
96        raise TranslationException(
97            'found obsolete entries in file.',
98            obsolete,
99        )
100
101    def reportinfo(self):
102        return (self.fspath, -1, "po-obsolete")
103
104
105class PoFuzzyItem(PoBaseItem):
106    def runtest(self):
107        parsed = open_po_file(self.fspath)
108
109        fuzzy = parsed.fuzzy_entries()
110
111        if not fuzzy:
112            return
113
114        raise TranslationException(
115            'found fuzzy entries in file.',
116            fuzzy,
117        )
118
119    def reportinfo(self):
120        return (self.fspath, -1, "po-fuzzy")
121