PageRenderTime 330ms CodeModel.GetById 30ms app.highlight 34ms RepoModel.GetById 25ms app.codeStats 0ms

/Lib/test/test_gettext.py

http://unladen-swallow.googlecode.com/
Python | 447 lines | 429 code | 5 blank | 13 comment | 2 complexity | 0f6c7448b0114cb4226de2a7601f36a7 MD5 | raw file
  1import os
  2import base64
  3import shutil
  4import gettext
  5import unittest
  6
  7from test import test_support
  8
  9
 10# TODO:
 11#  - Add new tests, for example for "dgettext"
 12#  - Remove dummy tests, for example testing for single and double quotes
 13#    has no sense, it would have if we were testing a parser (i.e. pygettext)
 14#  - Tests should have only one assert.
 15
 16GNU_MO_DATA = '''\
 173hIElQAAAAAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj
 18AAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD
 19AAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh
 20eW1vbmQgTHV4dXJ5IFlhY2gtdABUaGVyZSBpcyAlcyBmaWxlAFRoZXJlIGFyZSAlcyBmaWxlcwBU
 21aGlzIG1vZHVsZSBwcm92aWRlcyBpbnRlcm5hdGlvbmFsaXphdGlvbiBhbmQgbG9jYWxpemF0aW9u
 22CnN1cHBvcnQgZm9yIHlvdXIgUHl0aG9uIHByb2dyYW1zIGJ5IHByb3ZpZGluZyBhbiBpbnRlcmZh
 23Y2UgdG8gdGhlIEdOVQpnZXR0ZXh0IG1lc3NhZ2UgY2F0YWxvZyBsaWJyYXJ5LgBtdWxsdXNrAG51
 24ZGdlIG51ZGdlAFByb2plY3QtSWQtVmVyc2lvbjogMi4wClBPLVJldmlzaW9uLURhdGU6IDIwMDAt
 25MDgtMjkgMTI6MTktMDQ6MDAKTGFzdC1UcmFuc2xhdG9yOiBKLiBEYXZpZCBJYsOhw7FleiA8ai1k
 26YXZpZEBub29zLmZyPgpMYW5ndWFnZS1UZWFtOiBYWCA8cHl0aG9uLWRldkBweXRob24ub3JnPgpN
 27SU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9aXNvLTg4
 28NTktMQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBub25lCkdlbmVyYXRlZC1CeTogcHlnZXR0
 29ZXh0LnB5IDEuMQpQbHVyYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD1uIT0xOwoAVGhyb2F0
 30d29iYmxlciBNYW5ncm92ZQBIYXkgJXMgZmljaGVybwBIYXkgJXMgZmljaGVyb3MAR3V2ZiB6YnFo
 31eXIgY2ViaXZxcmYgdmFncmVhbmd2YmFueXZtbmd2YmEgbmFxIHlicG55dm1uZ3ZiYQpmaGNjYmVn
 32IHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1
 33ciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA==
 34'''
 35
 36UMO_DATA = '''\
 373hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABAAAAFEAAAAPAQAAVgAAAAQAAABm
 38AQAAAQAAAAIAAAAAAAAAAAAAAAAAAAAAYWLDngBQcm9qZWN0LUlkLVZlcnNpb246IDIuMApQTy1S
 39ZXZpc2lvbi1EYXRlOiAyMDAzLTA0LTExIDEyOjQyLTA0MDAKTGFzdC1UcmFuc2xhdG9yOiBCYXJy
 40eSBBLiBXQXJzYXcgPGJhcnJ5QHB5dGhvbi5vcmc+Ckxhbmd1YWdlLVRlYW06IFhYIDxweXRob24t
 41ZGV2QHB5dGhvbi5vcmc+Ck1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFp
 42bjsgY2hhcnNldD11dGYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA3Yml0CkdlbmVyYXRl
 43ZC1CeTogbWFudWFsbHkKAMKkeXoA
 44'''
 45
 46MMO_DATA = '''\
 473hIElQAAAAABAAAAHAAAACQAAAADAAAALAAAAAAAAAA4AAAAeAEAADkAAAABAAAAAAAAAAAAAAAA
 48UHJvamVjdC1JZC1WZXJzaW9uOiBObyBQcm9qZWN0IDAuMApQT1QtQ3JlYXRpb24tRGF0ZTogV2Vk
 49IERlYyAxMSAwNzo0NDoxNSAyMDAyClBPLVJldmlzaW9uLURhdGU6IDIwMDItMDgtMTQgMDE6MTg6
 50NTgrMDA6MDAKTGFzdC1UcmFuc2xhdG9yOiBKb2huIERvZSA8amRvZUBleGFtcGxlLmNvbT4KSmFu
 51ZSBGb29iYXIgPGpmb29iYXJAZXhhbXBsZS5jb20+Ckxhbmd1YWdlLVRlYW06IHh4IDx4eEBleGFt
 52cGxlLmNvbT4KTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFy
 53c2V0PWlzby04ODU5LTE1CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFi
 54bGUKR2VuZXJhdGVkLUJ5OiBweWdldHRleHQucHkgMS4zCgA=
 55'''
 56
 57LOCALEDIR = os.path.join('xx', 'LC_MESSAGES')
 58MOFILE = os.path.join(LOCALEDIR, 'gettext.mo')
 59UMOFILE = os.path.join(LOCALEDIR, 'ugettext.mo')
 60MMOFILE = os.path.join(LOCALEDIR, 'metadata.mo')
 61try:
 62    LANG = os.environ['LANGUAGE']
 63except:
 64    LANG = 'en'
 65
 66
 67class GettextBaseTest(unittest.TestCase):
 68    def setUp(self):
 69        if not os.path.isdir(LOCALEDIR):
 70            os.makedirs(LOCALEDIR)
 71        fp = open(MOFILE, 'wb')
 72        fp.write(base64.decodestring(GNU_MO_DATA))
 73        fp.close()
 74        fp = open(UMOFILE, 'wb')
 75        fp.write(base64.decodestring(UMO_DATA))
 76        fp.close()
 77        fp = open(MMOFILE, 'wb')
 78        fp.write(base64.decodestring(MMO_DATA))
 79        fp.close()
 80        os.environ['LANGUAGE'] = 'xx'
 81
 82    def tearDown(self):
 83        os.environ['LANGUAGE'] = LANG
 84        shutil.rmtree(os.path.split(LOCALEDIR)[0])
 85
 86
 87class GettextTestCase1(GettextBaseTest):
 88    def setUp(self):
 89        GettextBaseTest.setUp(self)
 90        self.localedir = os.curdir
 91        self.mofile = MOFILE
 92        gettext.install('gettext', self.localedir)
 93
 94    def test_some_translations(self):
 95        eq = self.assertEqual
 96        # test some translations
 97        eq(_('albatross'), 'albatross')
 98        eq(_(u'mullusk'), 'bacon')
 99        eq(_(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove')
100        eq(_(ur'nudge nudge'), 'wink wink')
101
102    def test_double_quotes(self):
103        eq = self.assertEqual
104        # double quotes
105        eq(_("albatross"), 'albatross')
106        eq(_(u"mullusk"), 'bacon')
107        eq(_(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove')
108        eq(_(ur"nudge nudge"), 'wink wink')
109
110    def test_triple_single_quotes(self):
111        eq = self.assertEqual
112        # triple single quotes
113        eq(_('''albatross'''), 'albatross')
114        eq(_(u'''mullusk'''), 'bacon')
115        eq(_(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove')
116        eq(_(ur'''nudge nudge'''), 'wink wink')
117
118    def test_triple_double_quotes(self):
119        eq = self.assertEqual
120        # triple double quotes
121        eq(_("""albatross"""), 'albatross')
122        eq(_(u"""mullusk"""), 'bacon')
123        eq(_(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove')
124        eq(_(ur"""nudge nudge"""), 'wink wink')
125
126    def test_multiline_strings(self):
127        eq = self.assertEqual
128        # multiline strings
129        eq(_('''This module provides internationalization and localization
130support for your Python programs by providing an interface to the GNU
131gettext message catalog library.'''),
132           '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba
133fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH
134trggrkg zrffntr pngnybt yvoenel.''')
135
136    def test_the_alternative_interface(self):
137        eq = self.assertEqual
138        # test the alternative interface
139        fp = open(self.mofile, 'rb')
140        t = gettext.GNUTranslations(fp)
141        fp.close()
142        # Install the translation object
143        t.install()
144        eq(_('nudge nudge'), 'wink wink')
145        # Try unicode return type
146        t.install(unicode=True)
147        eq(_('mullusk'), 'bacon')
148        # Test installation of other methods
149        import __builtin__
150        t.install(unicode=True, names=["gettext", "lgettext"])
151        eq(_, t.ugettext)
152        eq(__builtin__.gettext, t.ugettext)
153        eq(lgettext, t.lgettext)
154        del __builtin__.gettext
155        del __builtin__.lgettext
156
157
158class GettextTestCase2(GettextBaseTest):
159    def setUp(self):
160        GettextBaseTest.setUp(self)
161        self.localedir = os.curdir
162        # Set up the bindings
163        gettext.bindtextdomain('gettext', self.localedir)
164        gettext.textdomain('gettext')
165        # For convenience
166        self._ = gettext.gettext
167
168    def test_bindtextdomain(self):
169        self.assertEqual(gettext.bindtextdomain('gettext'), self.localedir)
170
171    def test_textdomain(self):
172        self.assertEqual(gettext.textdomain(), 'gettext')
173
174    def test_some_translations(self):
175        eq = self.assertEqual
176        # test some translations
177        eq(self._('albatross'), 'albatross')
178        eq(self._(u'mullusk'), 'bacon')
179        eq(self._(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove')
180        eq(self._(ur'nudge nudge'), 'wink wink')
181
182    def test_double_quotes(self):
183        eq = self.assertEqual
184        # double quotes
185        eq(self._("albatross"), 'albatross')
186        eq(self._(u"mullusk"), 'bacon')
187        eq(self._(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove')
188        eq(self._(ur"nudge nudge"), 'wink wink')
189
190    def test_triple_single_quotes(self):
191        eq = self.assertEqual
192        # triple single quotes
193        eq(self._('''albatross'''), 'albatross')
194        eq(self._(u'''mullusk'''), 'bacon')
195        eq(self._(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove')
196        eq(self._(ur'''nudge nudge'''), 'wink wink')
197
198    def test_triple_double_quotes(self):
199        eq = self.assertEqual
200        # triple double quotes
201        eq(self._("""albatross"""), 'albatross')
202        eq(self._(u"""mullusk"""), 'bacon')
203        eq(self._(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove')
204        eq(self._(ur"""nudge nudge"""), 'wink wink')
205
206    def test_multiline_strings(self):
207        eq = self.assertEqual
208        # multiline strings
209        eq(self._('''This module provides internationalization and localization
210support for your Python programs by providing an interface to the GNU
211gettext message catalog library.'''),
212           '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba
213fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH
214trggrkg zrffntr pngnybt yvoenel.''')
215
216
217class PluralFormsTestCase(GettextBaseTest):
218    def setUp(self):
219        GettextBaseTest.setUp(self)
220        self.mofile = MOFILE
221
222    def test_plural_forms1(self):
223        eq = self.assertEqual
224        x = gettext.ngettext('There is %s file', 'There are %s files', 1)
225        eq(x, 'Hay %s fichero')
226        x = gettext.ngettext('There is %s file', 'There are %s files', 2)
227        eq(x, 'Hay %s ficheros')
228
229    def test_plural_forms2(self):
230        eq = self.assertEqual
231        fp = open(self.mofile, 'rb')
232        t = gettext.GNUTranslations(fp)
233        fp.close()
234        x = t.ngettext('There is %s file', 'There are %s files', 1)
235        eq(x, 'Hay %s fichero')
236        x = t.ngettext('There is %s file', 'There are %s files', 2)
237        eq(x, 'Hay %s ficheros')
238
239    def test_hu(self):
240        eq = self.assertEqual
241        f = gettext.c2py('0')
242        s = ''.join([ str(f(x)) for x in range(200) ])
243        eq(s, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
244
245    def test_de(self):
246        eq = self.assertEqual
247        f = gettext.c2py('n != 1')
248        s = ''.join([ str(f(x)) for x in range(200) ])
249        eq(s, "10111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
250
251    def test_fr(self):
252        eq = self.assertEqual
253        f = gettext.c2py('n>1')
254        s = ''.join([ str(f(x)) for x in range(200) ])
255        eq(s, "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
256
257    def test_gd(self):
258        eq = self.assertEqual
259        f = gettext.c2py('n==1 ? 0 : n==2 ? 1 : 2')
260        s = ''.join([ str(f(x)) for x in range(200) ])
261        eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
262
263    def test_gd2(self):
264        eq = self.assertEqual
265        # Tests the combination of parentheses and "?:"
266        f = gettext.c2py('n==1 ? 0 : (n==2 ? 1 : 2)')
267        s = ''.join([ str(f(x)) for x in range(200) ])
268        eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
269
270    def test_lt(self):
271        eq = self.assertEqual
272        f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2')
273        s = ''.join([ str(f(x)) for x in range(200) ])
274        eq(s, "20111111112222222222201111111120111111112011111111201111111120111111112011111111201111111120111111112011111111222222222220111111112011111111201111111120111111112011111111201111111120111111112011111111")
275
276    def test_ru(self):
277        eq = self.assertEqual
278        f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2')
279        s = ''.join([ str(f(x)) for x in range(200) ])
280        eq(s, "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222")
281
282    def test_pl(self):
283        eq = self.assertEqual
284        f = gettext.c2py('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2')
285        s = ''.join([ str(f(x)) for x in range(200) ])
286        eq(s, "20111222222222222222221112222222111222222211122222221112222222111222222211122222221112222222111222222211122222222222222222111222222211122222221112222222111222222211122222221112222222111222222211122222")
287
288    def test_sl(self):
289        eq = self.assertEqual
290        f = gettext.c2py('n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3')
291        s = ''.join([ str(f(x)) for x in range(200) ])
292        eq(s, "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333")
293
294    def test_security(self):
295        raises = self.assertRaises
296        # Test for a dangerous expression
297        raises(ValueError, gettext.c2py, "os.chmod('/etc/passwd',0777)")
298
299
300class UnicodeTranslationsTest(GettextBaseTest):
301    def setUp(self):
302        GettextBaseTest.setUp(self)
303        fp = open(UMOFILE, 'rb')
304        try:
305            self.t = gettext.GNUTranslations(fp)
306        finally:
307            fp.close()
308        self._ = self.t.ugettext
309
310    def test_unicode_msgid(self):
311        unless = self.failUnless
312        unless(isinstance(self._(''), unicode))
313        unless(isinstance(self._(u''), unicode))
314
315    def test_unicode_msgstr(self):
316        eq = self.assertEqual
317        eq(self._(u'ab\xde'), u'\xa4yz')
318
319
320class WeirdMetadataTest(GettextBaseTest):
321    def setUp(self):
322        GettextBaseTest.setUp(self)
323        fp = open(MMOFILE, 'rb')
324        try:
325            try:
326                self.t = gettext.GNUTranslations(fp)
327            except:
328                self.tearDown()
329                raise
330        finally:
331            fp.close()
332
333    def test_weird_metadata(self):
334        info = self.t.info()
335        self.assertEqual(info['last-translator'],
336           'John Doe <jdoe@example.com>\nJane Foobar <jfoobar@example.com>')
337
338
339def test_main():
340    test_support.run_unittest(__name__)
341
342if __name__ == '__main__':
343    test_main()
344
345
346# For reference, here's the .po file used to created the GNU_MO_DATA above.
347#
348# The original version was automatically generated from the sources with
349# pygettext. Later it was manually modified to add plural forms support.
350
351'''
352# Dummy translation for the Python test_gettext.py module.
353# Copyright (C) 2001 Python Software Foundation
354# Barry Warsaw <barry@python.org>, 2000.
355#
356msgid ""
357msgstr ""
358"Project-Id-Version: 2.0\n"
359"PO-Revision-Date: 2003-04-11 14:32-0400\n"
360"Last-Translator: J. David Ibanez <j-david@noos.fr>\n"
361"Language-Team: XX <python-dev@python.org>\n"
362"MIME-Version: 1.0\n"
363"Content-Type: text/plain; charset=iso-8859-1\n"
364"Content-Transfer-Encoding: 8bit\n"
365"Generated-By: pygettext.py 1.1\n"
366"Plural-Forms: nplurals=2; plural=n!=1;\n"
367
368#: test_gettext.py:19 test_gettext.py:25 test_gettext.py:31 test_gettext.py:37
369#: test_gettext.py:51 test_gettext.py:80 test_gettext.py:86 test_gettext.py:92
370#: test_gettext.py:98
371msgid "nudge nudge"
372msgstr "wink wink"
373
374#: test_gettext.py:16 test_gettext.py:22 test_gettext.py:28 test_gettext.py:34
375#: test_gettext.py:77 test_gettext.py:83 test_gettext.py:89 test_gettext.py:95
376msgid "albatross"
377msgstr ""
378
379#: test_gettext.py:18 test_gettext.py:24 test_gettext.py:30 test_gettext.py:36
380#: test_gettext.py:79 test_gettext.py:85 test_gettext.py:91 test_gettext.py:97
381msgid "Raymond Luxury Yach-t"
382msgstr "Throatwobbler Mangrove"
383
384#: test_gettext.py:17 test_gettext.py:23 test_gettext.py:29 test_gettext.py:35
385#: test_gettext.py:56 test_gettext.py:78 test_gettext.py:84 test_gettext.py:90
386#: test_gettext.py:96
387msgid "mullusk"
388msgstr "bacon"
389
390#: test_gettext.py:40 test_gettext.py:101
391msgid ""
392"This module provides internationalization and localization\n"
393"support for your Python programs by providing an interface to the GNU\n"
394"gettext message catalog library."
395msgstr ""
396"Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba\n"
397"fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH\n"
398"trggrkg zrffntr pngnybt yvoenel."
399
400# Manually added, as neither pygettext nor xgettext support plural forms
401# in Python.
402msgid "There is %s file"
403msgid_plural "There are %s files"
404msgstr[0] "Hay %s fichero"
405msgstr[1] "Hay %s ficheros"
406'''
407
408# Here's the second example po file example, used to generate the UMO_DATA
409# containing utf-8 encoded Unicode strings
410
411'''
412# Dummy translation for the Python test_gettext.py module.
413# Copyright (C) 2001 Python Software Foundation
414# Barry Warsaw <barry@python.org>, 2000.
415#
416msgid ""
417msgstr ""
418"Project-Id-Version: 2.0\n"
419"PO-Revision-Date: 2003-04-11 12:42-0400\n"
420"Last-Translator: Barry A. WArsaw <barry@python.org>\n"
421"Language-Team: XX <python-dev@python.org>\n"
422"MIME-Version: 1.0\n"
423"Content-Type: text/plain; charset=utf-8\n"
424"Content-Transfer-Encoding: 7bit\n"
425"Generated-By: manually\n"
426
427#: nofile:0
428msgid "ab\xc3\x9e"
429msgstr "\xc2\xa4yz"
430'''
431
432# Here's the third example po file, used to generate MMO_DATA
433
434'''
435msgid ""
436msgstr ""
437"Project-Id-Version: No Project 0.0\n"
438"POT-Creation-Date: Wed Dec 11 07:44:15 2002\n"
439"PO-Revision-Date: 2002-08-14 01:18:58+00:00\n"
440"Last-Translator: John Doe <jdoe@example.com>\n"
441"Jane Foobar <jfoobar@example.com>\n"
442"Language-Team: xx <xx@example.com>\n"
443"MIME-Version: 1.0\n"
444"Content-Type: text/plain; charset=iso-8859-15\n"
445"Content-Transfer-Encoding: quoted-printable\n"
446"Generated-By: pygettext.py 1.3\n"
447'''