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') 61 62 63class GettextBaseTest(unittest.TestCase): 64 def setUp(self): 65 if not os.path.isdir(LOCALEDIR): 66 os.makedirs(LOCALEDIR) 67 with open(MOFILE, 'wb') as fp: 68 fp.write(base64.decodestring(GNU_MO_DATA)) 69 with open(UMOFILE, 'wb') as fp: 70 fp.write(base64.decodestring(UMO_DATA)) 71 with open(MMOFILE, 'wb') as fp: 72 fp.write(base64.decodestring(MMO_DATA)) 73 74 self.env = test_support.EnvironmentVarGuard() 75 self.env['LANGUAGE'] = 'xx' 76 gettext._translations.clear() 77 78 def tearDown(self): 79 self.env.__exit__() 80 del self.env 81 shutil.rmtree(os.path.split(LOCALEDIR)[0]) 82 83GNU_MO_DATA_ISSUE_17898 = b'''\ 843hIElQAAAAABAAAAHAAAACQAAAAAAAAAAAAAAAAAAAAsAAAAggAAAC0AAAAAUGx1cmFsLUZvcm1z 85OiBucGx1cmFscz0yOyBwbHVyYWw9KG4gIT0gMSk7CiMtIy0jLSMtIyAgbWVzc2FnZXMucG8gKEVk 86WCBTdHVkaW8pICAjLSMtIy0jLSMKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PVVU 87Ri04CgA= 88''' 89 90class GettextTestCase1(GettextBaseTest): 91 def setUp(self): 92 GettextBaseTest.setUp(self) 93 self.localedir = os.curdir 94 self.mofile = MOFILE 95 gettext.install('gettext', self.localedir) 96 97 def test_some_translations(self): 98 eq = self.assertEqual 99 # test some translations 100 eq(_('albatross'), 'albatross') 101 eq(_(u'mullusk'), 'bacon') 102 eq(_(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove') 103 eq(_(ur'nudge nudge'), 'wink wink') 104 105 def test_double_quotes(self): 106 eq = self.assertEqual 107 # double quotes 108 eq(_("albatross"), 'albatross') 109 eq(_(u"mullusk"), 'bacon') 110 eq(_(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove') 111 eq(_(ur"nudge nudge"), 'wink wink') 112 113 def test_triple_single_quotes(self): 114 eq = self.assertEqual 115 # triple single quotes 116 eq(_('''albatross'''), 'albatross') 117 eq(_(u'''mullusk'''), 'bacon') 118 eq(_(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove') 119 eq(_(ur'''nudge nudge'''), 'wink wink') 120 121 def test_triple_double_quotes(self): 122 eq = self.assertEqual 123 # triple double quotes 124 eq(_("""albatross"""), 'albatross') 125 eq(_(u"""mullusk"""), 'bacon') 126 eq(_(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove') 127 eq(_(ur"""nudge nudge"""), 'wink wink') 128 129 def test_multiline_strings(self): 130 eq = self.assertEqual 131 # multiline strings 132 eq(_('''This module provides internationalization and localization 133support for your Python programs by providing an interface to the GNU 134gettext message catalog library.'''), 135 '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba 136fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH 137trggrkg zrffntr pngnybt yvoenel.''') 138 139 def test_the_alternative_interface(self): 140 eq = self.assertEqual 141 # test the alternative interface 142 with open(self.mofile, 'rb') as fp: 143 t = gettext.GNUTranslations(fp) 144 # Install the translation object 145 t.install() 146 eq(_('nudge nudge'), 'wink wink') 147 # Try unicode return type 148 t.install(unicode=True) 149 eq(_('mullusk'), 'bacon') 150 # Test installation of other methods 151 import __builtin__ 152 t.install(unicode=True, names=["gettext", "lgettext"]) 153 eq(_, t.ugettext) 154 eq(__builtin__.gettext, t.ugettext) 155 eq(lgettext, t.lgettext) 156 del __builtin__.gettext 157 del __builtin__.lgettext 158 159 160class GettextTestCase2(GettextBaseTest): 161 def setUp(self): 162 GettextBaseTest.setUp(self) 163 self.localedir = os.curdir 164 # Set up the bindings 165 gettext.bindtextdomain('gettext', self.localedir) 166 gettext.textdomain('gettext') 167 # For convenience 168 self._ = gettext.gettext 169 170 def test_bindtextdomain(self): 171 self.assertEqual(gettext.bindtextdomain('gettext'), self.localedir) 172 173 def test_textdomain(self): 174 self.assertEqual(gettext.textdomain(), 'gettext') 175 176 def test_some_translations(self): 177 eq = self.assertEqual 178 # test some translations 179 eq(self._('albatross'), 'albatross') 180 eq(self._(u'mullusk'), 'bacon') 181 eq(self._(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove') 182 eq(self._(ur'nudge nudge'), 'wink wink') 183 184 def test_double_quotes(self): 185 eq = self.assertEqual 186 # double quotes 187 eq(self._("albatross"), 'albatross') 188 eq(self._(u"mullusk"), 'bacon') 189 eq(self._(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove') 190 eq(self._(ur"nudge nudge"), 'wink wink') 191 192 def test_triple_single_quotes(self): 193 eq = self.assertEqual 194 # triple single quotes 195 eq(self._('''albatross'''), 'albatross') 196 eq(self._(u'''mullusk'''), 'bacon') 197 eq(self._(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove') 198 eq(self._(ur'''nudge nudge'''), 'wink wink') 199 200 def test_triple_double_quotes(self): 201 eq = self.assertEqual 202 # triple double quotes 203 eq(self._("""albatross"""), 'albatross') 204 eq(self._(u"""mullusk"""), 'bacon') 205 eq(self._(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove') 206 eq(self._(ur"""nudge nudge"""), 'wink wink') 207 208 def test_multiline_strings(self): 209 eq = self.assertEqual 210 # multiline strings 211 eq(self._('''This module provides internationalization and localization 212support for your Python programs by providing an interface to the GNU 213gettext message catalog library.'''), 214 '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba 215fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH 216trggrkg zrffntr pngnybt yvoenel.''') 217 218 219class PluralFormsTestCase(GettextBaseTest): 220 def setUp(self): 221 GettextBaseTest.setUp(self) 222 self.mofile = MOFILE 223 224 def test_plural_forms1(self): 225 eq = self.assertEqual 226 x = gettext.ngettext('There is %s file', 'There are %s files', 1) 227 eq(x, 'Hay %s fichero') 228 x = gettext.ngettext('There is %s file', 'There are %s files', 2) 229 eq(x, 'Hay %s ficheros') 230 231 def test_plural_forms2(self): 232 eq = self.assertEqual 233 with open(self.mofile, 'rb') as fp: 234 t = gettext.GNUTranslations(fp) 235 x = t.ngettext('There is %s file', 'There are %s files', 1) 236 eq(x, 'Hay %s fichero') 237 x = t.ngettext('There is %s file', 'There are %s files', 2) 238 eq(x, 'Hay %s ficheros') 239 240 # Examples from http://www.gnu.org/software/gettext/manual/gettext.html 241 242 def test_ja(self): 243 eq = self.assertEqual 244 f = gettext.c2py('0') 245 s = ''.join([ str(f(x)) for x in range(200) ]) 246 eq(s, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") 247 248 def test_de(self): 249 eq = self.assertEqual 250 f = gettext.c2py('n != 1') 251 s = ''.join([ str(f(x)) for x in range(200) ]) 252 eq(s, "10111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") 253 254 def test_fr(self): 255 eq = self.assertEqual 256 f = gettext.c2py('n>1') 257 s = ''.join([ str(f(x)) for x in range(200) ]) 258 eq(s, "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") 259 260 def test_lv(self): 261 eq = self.assertEqual 262 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2') 263 s = ''.join([ str(f(x)) for x in range(200) ]) 264 eq(s, "20111111111111111111101111111110111111111011111111101111111110111111111011111111101111111110111111111011111111111111111110111111111011111111101111111110111111111011111111101111111110111111111011111111") 265 266 def test_gd(self): 267 eq = self.assertEqual 268 f = gettext.c2py('n==1 ? 0 : n==2 ? 1 : 2') 269 s = ''.join([ str(f(x)) for x in range(200) ]) 270 eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") 271 272 def test_gd2(self): 273 eq = self.assertEqual 274 # Tests the combination of parentheses and "?:" 275 f = gettext.c2py('n==1 ? 0 : (n==2 ? 1 : 2)') 276 s = ''.join([ str(f(x)) for x in range(200) ]) 277 eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") 278 279 def test_ro(self): 280 eq = self.assertEqual 281 f = gettext.c2py('n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2') 282 s = ''.join([ str(f(x)) for x in range(200) ]) 283 eq(s, "10111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222") 284 285 def test_lt(self): 286 eq = self.assertEqual 287 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2') 288 s = ''.join([ str(f(x)) for x in range(200) ]) 289 eq(s, "20111111112222222222201111111120111111112011111111201111111120111111112011111111201111111120111111112011111111222222222220111111112011111111201111111120111111112011111111201111111120111111112011111111") 290 291 def test_ru(self): 292 eq = self.assertEqual 293 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2') 294 s = ''.join([ str(f(x)) for x in range(200) ]) 295 eq(s, "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222") 296 297 def test_cs(self): 298 eq = self.assertEqual 299 f = gettext.c2py('(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2') 300 s = ''.join([ str(f(x)) for x in range(200) ]) 301 eq(s, "20111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") 302 303 def test_pl(self): 304 eq = self.assertEqual 305 f = gettext.c2py('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2') 306 s = ''.join([ str(f(x)) for x in range(200) ]) 307 eq(s, "20111222222222222222221112222222111222222211122222221112222222111222222211122222221112222222111222222211122222222222222222111222222211122222221112222222111222222211122222221112222222111222222211122222") 308 309 def test_sl(self): 310 eq = self.assertEqual 311 f = gettext.c2py('n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3') 312 s = ''.join([ str(f(x)) for x in range(200) ]) 313 eq(s, "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333") 314 315 def test_ar(self): 316 eq = self.assertEqual 317 f = gettext.c2py('n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5') 318 s = ''.join([ str(f(x)) for x in range(200) ]) 319 eq(s, "01233333333444444444444444444444444444444444444444444444444444444444444444444444444444444444444444445553333333344444444444444444444444444444444444444444444444444444444444444444444444444444444444444444") 320 321 def test_security(self): 322 raises = self.assertRaises 323 # Test for a dangerous expression 324 raises(ValueError, gettext.c2py, "os.chmod('/etc/passwd',0777)") 325 # issue28563 326 raises(ValueError, gettext.c2py, '"(eval(foo) && ""') 327 raises(ValueError, gettext.c2py, 'f"{os.system(\'sh\')}"') 328 # Maximum recursion depth exceeded during compilation 329 raises(ValueError, gettext.c2py, 'n+'*10000 + 'n') 330 self.assertEqual(gettext.c2py('n+'*100 + 'n')(1), 101) 331 # MemoryError during compilation 332 raises(ValueError, gettext.c2py, '('*100 + 'n' + ')'*100) 333 # Maximum recursion depth exceeded in C to Python translator 334 raises(ValueError, gettext.c2py, '('*10000 + 'n' + ')'*10000) 335 self.assertEqual(gettext.c2py('('*20 + 'n' + ')'*20)(1), 1) 336 337 def test_chained_comparison(self): 338 # C doesn't chain comparison as Python so 2 == 2 == 2 gets different results 339 f = gettext.c2py('n == n == n') 340 self.assertEqual(''.join(str(f(x)) for x in range(3)), '010') 341 f = gettext.c2py('1 < n == n') 342 self.assertEqual(''.join(str(f(x)) for x in range(3)), '100') 343 f = gettext.c2py('n == n < 2') 344 self.assertEqual(''.join(str(f(x)) for x in range(3)), '010') 345 f = gettext.c2py('0 < n < 2') 346 self.assertEqual(''.join(str(f(x)) for x in range(3)), '111') 347 348 def test_decimal_number(self): 349 self.assertEqual(gettext.c2py('0123')(1), 123) 350 351 def test_invalid_syntax(self): 352 invalid_expressions = [ 353 'x>1', '(n>1', 'n>1)', '42**42**42', '0xa', '1.0', '1e2', 354 'n>0x1', '+n', '-n', 'n()', 'n(1)', '1+', 'nn', 'n n', 355 ] 356 for expr in invalid_expressions: 357 with self.assertRaises(ValueError): 358 gettext.c2py(expr) 359 360 def test_nested_condition_operator(self): 361 self.assertEqual(gettext.c2py('n?1?2:3:4')(0), 4) 362 self.assertEqual(gettext.c2py('n?1?2:3:4')(1), 2) 363 self.assertEqual(gettext.c2py('n?1:3?4:5')(0), 4) 364 self.assertEqual(gettext.c2py('n?1:3?4:5')(1), 1) 365 366 def test_division(self): 367 f = gettext.c2py('2/n*3') 368 self.assertEqual(f(1), 6) 369 self.assertEqual(f(2), 3) 370 self.assertEqual(f(3), 0) 371 self.assertEqual(f(-1), -6) 372 self.assertRaises(ZeroDivisionError, f, 0) 373 374 def test_plural_number(self): 375 f = gettext.c2py('n != 1') 376 self.assertEqual(f(1), 0) 377 self.assertEqual(f(2), 1) 378 self.assertEqual(f(1.0), 0) 379 self.assertEqual(f(2.0), 1) 380 self.assertEqual(f(1.1), 1) 381 self.assertRaises(TypeError, f, '2') 382 self.assertRaises(TypeError, f, b'2') 383 self.assertRaises(TypeError, f, []) 384 self.assertRaises(TypeError, f, object()) 385 386 387class GNUTranslationParsingTest(GettextBaseTest): 388 def test_plural_form_error_issue17898(self): 389 with open(MOFILE, 'wb') as fp: 390 fp.write(base64.decodestring(GNU_MO_DATA_ISSUE_17898)) 391 with open(MOFILE, 'rb') as fp: 392 # If this runs cleanly, the bug is fixed. 393 t = gettext.GNUTranslations(fp) 394 395 396class UnicodeTranslationsTest(GettextBaseTest): 397 def setUp(self): 398 GettextBaseTest.setUp(self) 399 with open(UMOFILE, 'rb') as fp: 400 self.t = gettext.GNUTranslations(fp) 401 self._ = self.t.ugettext 402 403 def test_unicode_msgid(self): 404 unless = self.assertTrue 405 unless(isinstance(self._(''), unicode)) 406 unless(isinstance(self._(u''), unicode)) 407 408 def test_unicode_msgstr(self): 409 eq = self.assertEqual 410 eq(self._(u'ab\xde'), u'\xa4yz') 411 412 413class WeirdMetadataTest(GettextBaseTest): 414 def setUp(self): 415 GettextBaseTest.setUp(self) 416 with open(MMOFILE, 'rb') as fp: 417 try: 418 self.t = gettext.GNUTranslations(fp) 419 except: 420 self.tearDown() 421 raise 422 423 def test_weird_metadata(self): 424 info = self.t.info() 425 self.assertEqual(info['last-translator'], 426 'John Doe <jdoe@example.com>\nJane Foobar <jfoobar@example.com>') 427 428 429class DummyGNUTranslations(gettext.GNUTranslations): 430 def foo(self): 431 return 'foo' 432 433 434class GettextCacheTestCase(GettextBaseTest): 435 def test_cache(self): 436 self.localedir = os.curdir 437 self.mofile = MOFILE 438 439 self.assertEqual(len(gettext._translations), 0) 440 441 t = gettext.translation('gettext', self.localedir) 442 443 self.assertEqual(len(gettext._translations), 1) 444 445 t = gettext.translation('gettext', self.localedir, 446 class_=DummyGNUTranslations) 447 448 self.assertEqual(len(gettext._translations), 2) 449 self.assertEqual(t.__class__, DummyGNUTranslations) 450 451 # Calling it again doesn't add to the cache 452 453 t = gettext.translation('gettext', self.localedir, 454 class_=DummyGNUTranslations) 455 456 self.assertEqual(len(gettext._translations), 2) 457 self.assertEqual(t.__class__, DummyGNUTranslations) 458 459 460def test_main(): 461 test_support.run_unittest(__name__) 462 463if __name__ == '__main__': 464 test_main() 465 466 467# For reference, here's the .po file used to created the GNU_MO_DATA above. 468# 469# The original version was automatically generated from the sources with 470# pygettext. Later it was manually modified to add plural forms support. 471 472''' 473# Dummy translation for the Python test_gettext.py module. 474# Copyright (C) 2001 Python Software Foundation 475# Barry Warsaw <barry@python.org>, 2000. 476# 477msgid "" 478msgstr "" 479"Project-Id-Version: 2.0\n" 480"PO-Revision-Date: 2003-04-11 14:32-0400\n" 481"Last-Translator: J. David Ibanez <j-david@noos.fr>\n" 482"Language-Team: XX <python-dev@python.org>\n" 483"MIME-Version: 1.0\n" 484"Content-Type: text/plain; charset=iso-8859-1\n" 485"Content-Transfer-Encoding: 8bit\n" 486"Generated-By: pygettext.py 1.1\n" 487"Plural-Forms: nplurals=2; plural=n!=1;\n" 488 489#: test_gettext.py:19 test_gettext.py:25 test_gettext.py:31 test_gettext.py:37 490#: test_gettext.py:51 test_gettext.py:80 test_gettext.py:86 test_gettext.py:92 491#: test_gettext.py:98 492msgid "nudge nudge" 493msgstr "wink wink" 494 495#: test_gettext.py:16 test_gettext.py:22 test_gettext.py:28 test_gettext.py:34 496#: test_gettext.py:77 test_gettext.py:83 test_gettext.py:89 test_gettext.py:95 497msgid "albatross" 498msgstr "" 499 500#: test_gettext.py:18 test_gettext.py:24 test_gettext.py:30 test_gettext.py:36 501#: test_gettext.py:79 test_gettext.py:85 test_gettext.py:91 test_gettext.py:97 502msgid "Raymond Luxury Yach-t" 503msgstr "Throatwobbler Mangrove" 504 505#: test_gettext.py:17 test_gettext.py:23 test_gettext.py:29 test_gettext.py:35 506#: test_gettext.py:56 test_gettext.py:78 test_gettext.py:84 test_gettext.py:90 507#: test_gettext.py:96 508msgid "mullusk" 509msgstr "bacon" 510 511#: test_gettext.py:40 test_gettext.py:101 512msgid "" 513"This module provides internationalization and localization\n" 514"support for your Python programs by providing an interface to the GNU\n" 515"gettext message catalog library." 516msgstr "" 517"Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba\n" 518"fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH\n" 519"trggrkg zrffntr pngnybt yvoenel." 520 521# Manually added, as neither pygettext nor xgettext support plural forms 522# in Python. 523msgid "There is %s file" 524msgid_plural "There are %s files" 525msgstr[0] "Hay %s fichero" 526msgstr[1] "Hay %s ficheros" 527''' 528 529# Here's the second example po file example, used to generate the UMO_DATA 530# containing utf-8 encoded Unicode strings 531 532''' 533# Dummy translation for the Python test_gettext.py module. 534# Copyright (C) 2001 Python Software Foundation 535# Barry Warsaw <barry@python.org>, 2000. 536# 537msgid "" 538msgstr "" 539"Project-Id-Version: 2.0\n" 540"PO-Revision-Date: 2003-04-11 12:42-0400\n" 541"Last-Translator: Barry A. WArsaw <barry@python.org>\n" 542"Language-Team: XX <python-dev@python.org>\n" 543"MIME-Version: 1.0\n" 544"Content-Type: text/plain; charset=utf-8\n" 545"Content-Transfer-Encoding: 7bit\n" 546"Generated-By: manually\n" 547 548#: nofile:0 549msgid "ab\xc3\x9e" 550msgstr "\xc2\xa4yz" 551''' 552 553# Here's the third example po file, used to generate MMO_DATA 554 555''' 556msgid "" 557msgstr "" 558"Project-Id-Version: No Project 0.0\n" 559"POT-Creation-Date: Wed Dec 11 07:44:15 2002\n" 560"PO-Revision-Date: 2002-08-14 01:18:58+00:00\n" 561"Last-Translator: John Doe <jdoe@example.com>\n" 562"Jane Foobar <jfoobar@example.com>\n" 563"Language-Team: xx <xx@example.com>\n" 564"MIME-Version: 1.0\n" 565"Content-Type: text/plain; charset=iso-8859-15\n" 566"Content-Transfer-Encoding: quoted-printable\n" 567"Generated-By: pygettext.py 1.3\n" 568''' 569 570# 571# messages.po, used for bug 17898 572# 573 574''' 575# test file for http://bugs.python.org/issue17898 576msgid "" 577msgstr "" 578"Plural-Forms: nplurals=2; plural=(n != 1);\n" 579"#-#-#-#-# messages.po (EdX Studio) #-#-#-#-#\n" 580"Content-Type: text/plain; charset=UTF-8\n" 581''' 582