Fixed minor bug with indented section titles being discovered when they should not.
[docutils.git] / test / test_language.py
blob79509b46a4da69bada36c6be75dd7efe04c7f78a
1 #!/usr/bin/env python
3 # Authors: Engelbert Gruber; David Goodger
4 # Contact: grubert@users.sourceforge.net
5 # Revision: $Revision$
6 # Date: $Date$
7 # Copyright: This module has been placed in the public domain.
9 """
10 Tests for language module completeness.
12 Specify a language code (e.g. "de") as a command-line parameter to test only
13 that language.
14 """
16 import sys
17 import os
18 import re
19 from types import UnicodeType
20 import docutils.languages
21 import docutils.parsers.rst.languages
22 from docutils.parsers.rst import states, directives, roles
23 from DocutilsTestSupport import CustomTestSuite, CustomTestCase
25 reference_language = 'en'
28 class LanguageTestSuite(CustomTestSuite):
30 language_module_pattern = re.compile('^([a-z]{2,3}(_[a-z]{2,8})*)\.py$')
32 def __init__(self, languages=None):
33 CustomTestSuite.__init__(self)
34 if languages:
35 self.languages = languages
36 else:
37 self.get_languages()
39 def get_languages(self):
40 """
41 Get installed language translations from docutils.languages and from
42 docutils.parsers.rst.languages.
43 """
44 languages = {}
45 for mod in (os.listdir(docutils.languages.__path__[0])
46 + os.listdir(docutils.parsers.rst.languages.__path__[0])):
47 match = self.language_module_pattern.match(mod)
48 if match:
49 languages[match.group(1)] = 1
50 self.languages = languages.keys()
52 def generateTests(self):
53 for language in self.languages:
54 for method in LanguageTestCase.test_methods:
55 self.addTestCase(LanguageTestCase, method, None, None,
56 id=language+'.py', language=language)
59 class LanguageTestCase(CustomTestCase):
61 test_methods = ['test_labels', 'test_bibliographic_fields',
62 'test_directives', 'test_roles']
63 """Names of methods used to test each language."""
65 def __init__(self, *args, **kwargs):
66 self.ref = docutils.languages.get_language(reference_language)
67 self.language = kwargs['language']
68 del kwargs['language'] # only wanted here
69 CustomTestCase.__init__(self, *args, **kwargs)
71 def _xor(self, ref_dict, l_dict):
72 """
73 Returns entries that are only in one dictionary.
74 (missing_in_lang, more_than_in_ref).
75 """
76 missing = [] # in ref but not in l.
77 too_much = [] # in l but not in ref.
78 for label in ref_dict.keys():
79 if not l_dict.has_key(label):
80 missing.append(label)
81 for label in l_dict.keys():
82 if not ref_dict.has_key(label):
83 too_much.append(label)
84 return (missing, too_much)
86 def _invert(self, adict):
87 """Return an inverted (keys & values swapped) dictionary."""
88 inverted = {}
89 for key, value in adict.items():
90 inverted[value] = key
91 return inverted
93 def test_labels(self):
94 try:
95 module = docutils.languages.get_language(self.language)
96 if not module:
97 raise ImportError
98 except ImportError:
99 self.fail('No docutils.languages.%s module.' % self.language)
100 missed, unknown = self._xor(self.ref.labels, module.labels)
101 if missed or unknown:
102 self.fail('Module docutils.languages.%s.labels:\n'
103 ' Missed: %s; Unknown: %s'
104 % (self.language, str(missed), str(unknown)))
106 def test_bibliographic_fields(self):
107 try:
108 module = docutils.languages.get_language(self.language)
109 if not module:
110 raise ImportError
111 except ImportError:
112 self.fail('No docutils.languages.%s module.' % self.language)
113 missed, unknown = self._xor(
114 self._invert(self.ref.bibliographic_fields),
115 self._invert(module.bibliographic_fields))
116 if missed or unknown:
117 self.fail('Module docutils.languages.%s.bibliographic_fields:\n'
118 ' Missed: %s; Unknown: %s'
119 % (self.language, str(missed), str(unknown)))
121 def test_directives(self):
122 try:
123 module = docutils.parsers.rst.languages.get_language(
124 self.language)
125 if not module:
126 raise ImportError
127 except ImportError:
128 self.fail('No docutils.parsers.rst.languages.%s module.'
129 % self.language)
130 failures = []
131 for d in module.directives.keys():
132 try:
133 func, msg = directives.directive(d, module, None)
134 if not func:
135 failures.append('"%s": unknown directive' % d)
136 except Exception, error:
137 failures.append('"%s": %s' % (d, error))
138 inverted = self._invert(module.directives)
139 canonical = directives._directive_registry.keys()
140 canonical.sort()
141 canonical.remove('restructuredtext-test-directive')
142 for name in canonical:
143 if not inverted.has_key(name):
144 failures.append('"%s": translation missing' % name)
145 if failures:
146 text = ('Module docutils.parsers.rst.languages.%s:\n %s'
147 % (self.language, '\n '.join(failures)))
148 if type(text) == UnicodeType:
149 text = text.encode('raw_unicode_escape')
150 self.fail(text)
152 def test_roles(self):
153 try:
154 module = docutils.parsers.rst.languages.get_language(
155 self.language)
156 if not module:
157 raise ImportError
158 module.roles
159 except ImportError:
160 self.fail('No docutils.parsers.rst.languages.%s module.'
161 % self.language)
162 except AttributeError:
163 self.fail('No "roles" mapping in docutils.parsers.rst.languages.'
164 '%s module.' % self.language)
165 failures = []
166 for d in module.roles.values():
167 try:
168 method = roles._role_registry[d]
169 #if not method:
170 # failures.append('"%s": unknown role' % d)
171 except KeyError, error:
172 failures.append('"%s": %s' % (d, error))
173 inverted = self._invert(module.roles)
174 canonical = roles._role_registry.keys()
175 canonical.sort()
176 canonical.remove('restructuredtext-unimplemented-role')
177 for name in canonical:
178 if not inverted.has_key(name):
179 failures.append('"%s": translation missing' % name)
180 if failures:
181 text = ('Module docutils.parsers.rst.languages.%s:\n %s'
182 % (self.language, '\n '.join(failures)))
183 if type(text) == UnicodeType:
184 text = text.encode('raw_unicode_escape')
185 self.fail(text)
188 languages_to_test = []
190 def suite():
191 s = LanguageTestSuite(languages_to_test)
192 s.generateTests()
193 return s
195 def get_language_arguments():
196 while len(sys.argv) > 1:
197 last = sys.argv[-1]
198 if last.startswith('-'):
199 break
200 languages_to_test.append(last)
201 sys.argv.pop()
202 languages_to_test.reverse()
205 if __name__ == '__main__':
206 get_language_arguments()
207 import unittest
208 unittest.main(defaultTest='suite')
210 # vim: set et ts=4 ai :