ยปCore Development>Code coverage>Lib/test/test_gettext.py

Python code coverage for Lib/test/test_gettext.py

#countcontent
1n/aimport os
2n/aimport base64
3n/aimport gettext
4n/aimport unittest
5n/a
6n/afrom test import support
7n/a
8n/a
9n/a# TODO:
10n/a# - Add new tests, for example for "dgettext"
11n/a# - Remove dummy tests, for example testing for single and double quotes
12n/a# has no sense, it would have if we were testing a parser (i.e. pygettext)
13n/a# - Tests should have only one assert.
14n/a
15n/aGNU_MO_DATA = b'''\
16n/a3hIElQAAAAAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj
17n/aAAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD
18n/aAAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh
19n/aeW1vbmQgTHV4dXJ5IFlhY2gtdABUaGVyZSBpcyAlcyBmaWxlAFRoZXJlIGFyZSAlcyBmaWxlcwBU
20n/aaGlzIG1vZHVsZSBwcm92aWRlcyBpbnRlcm5hdGlvbmFsaXphdGlvbiBhbmQgbG9jYWxpemF0aW9u
21n/aCnN1cHBvcnQgZm9yIHlvdXIgUHl0aG9uIHByb2dyYW1zIGJ5IHByb3ZpZGluZyBhbiBpbnRlcmZh
22n/aY2UgdG8gdGhlIEdOVQpnZXR0ZXh0IG1lc3NhZ2UgY2F0YWxvZyBsaWJyYXJ5LgBtdWxsdXNrAG51
23n/aZGdlIG51ZGdlAFByb2plY3QtSWQtVmVyc2lvbjogMi4wClBPLVJldmlzaW9uLURhdGU6IDIwMDAt
24n/aMDgtMjkgMTI6MTktMDQ6MDAKTGFzdC1UcmFuc2xhdG9yOiBKLiBEYXZpZCBJYsOhw7FleiA8ai1k
25n/aYXZpZEBub29zLmZyPgpMYW5ndWFnZS1UZWFtOiBYWCA8cHl0aG9uLWRldkBweXRob24ub3JnPgpN
26n/aSU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9aXNvLTg4
27n/aNTktMQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBub25lCkdlbmVyYXRlZC1CeTogcHlnZXR0
28n/aZXh0LnB5IDEuMQpQbHVyYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD1uIT0xOwoAVGhyb2F0
29n/ad29iYmxlciBNYW5ncm92ZQBIYXkgJXMgZmljaGVybwBIYXkgJXMgZmljaGVyb3MAR3V2ZiB6YnFo
30n/aeXIgY2ViaXZxcmYgdmFncmVhbmd2YmFueXZtbmd2YmEgbmFxIHlicG55dm1uZ3ZiYQpmaGNjYmVn
31n/aIHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1
32n/aciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA==
33n/a'''
34n/a
35n/a# This data contains an invalid major version number (5)
36n/a# An unexpected major version number should be treated as an error when
37n/a# parsing a .mo file
38n/a
39n/aGNU_MO_DATA_BAD_MAJOR_VERSION = b'''\
40n/a3hIElQAABQAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj
41n/aAAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD
42n/aAAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh
43n/aeW1vbmQgTHV4dXJ5IFlhY2gtdABUaGVyZSBpcyAlcyBmaWxlAFRoZXJlIGFyZSAlcyBmaWxlcwBU
44n/aaGlzIG1vZHVsZSBwcm92aWRlcyBpbnRlcm5hdGlvbmFsaXphdGlvbiBhbmQgbG9jYWxpemF0aW9u
45n/aCnN1cHBvcnQgZm9yIHlvdXIgUHl0aG9uIHByb2dyYW1zIGJ5IHByb3ZpZGluZyBhbiBpbnRlcmZh
46n/aY2UgdG8gdGhlIEdOVQpnZXR0ZXh0IG1lc3NhZ2UgY2F0YWxvZyBsaWJyYXJ5LgBtdWxsdXNrAG51
47n/aZGdlIG51ZGdlAFByb2plY3QtSWQtVmVyc2lvbjogMi4wClBPLVJldmlzaW9uLURhdGU6IDIwMDAt
48n/aMDgtMjkgMTI6MTktMDQ6MDAKTGFzdC1UcmFuc2xhdG9yOiBKLiBEYXZpZCBJYsOhw7FleiA8ai1k
49n/aYXZpZEBub29zLmZyPgpMYW5ndWFnZS1UZWFtOiBYWCA8cHl0aG9uLWRldkBweXRob24ub3JnPgpN
50n/aSU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9aXNvLTg4
51n/aNTktMQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBub25lCkdlbmVyYXRlZC1CeTogcHlnZXR0
52n/aZXh0LnB5IDEuMQpQbHVyYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD1uIT0xOwoAVGhyb2F0
53n/ad29iYmxlciBNYW5ncm92ZQBIYXkgJXMgZmljaGVybwBIYXkgJXMgZmljaGVyb3MAR3V2ZiB6YnFo
54n/aeXIgY2ViaXZxcmYgdmFncmVhbmd2YmFueXZtbmd2YmEgbmFxIHlicG55dm1uZ3ZiYQpmaGNjYmVn
55n/aIHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1
56n/aciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA==
57n/a'''
58n/a
59n/a# This data contains an invalid minor version number (7)
60n/a# An unexpected minor version number only indicates that some of the file's
61n/a# contents may not be able to be read. It does not indicate an error.
62n/a
63n/aGNU_MO_DATA_BAD_MINOR_VERSION = b'''\
64n/a3hIElQcAAAAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj
65n/aAAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD
66n/aAAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh
67n/aeW1vbmQgTHV4dXJ5IFlhY2gtdABUaGVyZSBpcyAlcyBmaWxlAFRoZXJlIGFyZSAlcyBmaWxlcwBU
68n/aaGlzIG1vZHVsZSBwcm92aWRlcyBpbnRlcm5hdGlvbmFsaXphdGlvbiBhbmQgbG9jYWxpemF0aW9u
69n/aCnN1cHBvcnQgZm9yIHlvdXIgUHl0aG9uIHByb2dyYW1zIGJ5IHByb3ZpZGluZyBhbiBpbnRlcmZh
70n/aY2UgdG8gdGhlIEdOVQpnZXR0ZXh0IG1lc3NhZ2UgY2F0YWxvZyBsaWJyYXJ5LgBtdWxsdXNrAG51
71n/aZGdlIG51ZGdlAFByb2plY3QtSWQtVmVyc2lvbjogMi4wClBPLVJldmlzaW9uLURhdGU6IDIwMDAt
72n/aMDgtMjkgMTI6MTktMDQ6MDAKTGFzdC1UcmFuc2xhdG9yOiBKLiBEYXZpZCBJYsOhw7FleiA8ai1k
73n/aYXZpZEBub29zLmZyPgpMYW5ndWFnZS1UZWFtOiBYWCA8cHl0aG9uLWRldkBweXRob24ub3JnPgpN
74n/aSU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9aXNvLTg4
75n/aNTktMQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBub25lCkdlbmVyYXRlZC1CeTogcHlnZXR0
76n/aZXh0LnB5IDEuMQpQbHVyYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD1uIT0xOwoAVGhyb2F0
77n/ad29iYmxlciBNYW5ncm92ZQBIYXkgJXMgZmljaGVybwBIYXkgJXMgZmljaGVyb3MAR3V2ZiB6YnFo
78n/aeXIgY2ViaXZxcmYgdmFncmVhbmd2YmFueXZtbmd2YmEgbmFxIHlicG55dm1uZ3ZiYQpmaGNjYmVn
79n/aIHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1
80n/aciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA==
81n/a'''
82n/a
83n/a
84n/aUMO_DATA = b'''\
85n/a3hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABAAAAFEAAAAPAQAAVgAAAAQAAABm
86n/aAQAAAQAAAAIAAAAAAAAAAAAAAAAAAAAAYWLDngBQcm9qZWN0LUlkLVZlcnNpb246IDIuMApQTy1S
87n/aZXZpc2lvbi1EYXRlOiAyMDAzLTA0LTExIDEyOjQyLTA0MDAKTGFzdC1UcmFuc2xhdG9yOiBCYXJy
88n/aeSBBLiBXQXJzYXcgPGJhcnJ5QHB5dGhvbi5vcmc+Ckxhbmd1YWdlLVRlYW06IFhYIDxweXRob24t
89n/aZGV2QHB5dGhvbi5vcmc+Ck1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFp
90n/abjsgY2hhcnNldD11dGYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA3Yml0CkdlbmVyYXRl
91n/aZC1CeTogbWFudWFsbHkKAMKkeXoA
92n/a'''
93n/a
94n/aMMO_DATA = b'''\
95n/a3hIElQAAAAABAAAAHAAAACQAAAADAAAALAAAAAAAAAA4AAAAeAEAADkAAAABAAAAAAAAAAAAAAAA
96n/aUHJvamVjdC1JZC1WZXJzaW9uOiBObyBQcm9qZWN0IDAuMApQT1QtQ3JlYXRpb24tRGF0ZTogV2Vk
97n/aIERlYyAxMSAwNzo0NDoxNSAyMDAyClBPLVJldmlzaW9uLURhdGU6IDIwMDItMDgtMTQgMDE6MTg6
98n/aNTgrMDA6MDAKTGFzdC1UcmFuc2xhdG9yOiBKb2huIERvZSA8amRvZUBleGFtcGxlLmNvbT4KSmFu
99n/aZSBGb29iYXIgPGpmb29iYXJAZXhhbXBsZS5jb20+Ckxhbmd1YWdlLVRlYW06IHh4IDx4eEBleGFt
100n/acGxlLmNvbT4KTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFy
101n/ac2V0PWlzby04ODU5LTE1CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFi
102n/abGUKR2VuZXJhdGVkLUJ5OiBweWdldHRleHQucHkgMS4zCgA=
103n/a'''
104n/a
105n/aLOCALEDIR = os.path.join('xx', 'LC_MESSAGES')
106n/aMOFILE = os.path.join(LOCALEDIR, 'gettext.mo')
107n/aMOFILE_BAD_MAJOR_VERSION = os.path.join(LOCALEDIR, 'gettext_bad_major_version.mo')
108n/aMOFILE_BAD_MINOR_VERSION = os.path.join(LOCALEDIR, 'gettext_bad_minor_version.mo')
109n/aUMOFILE = os.path.join(LOCALEDIR, 'ugettext.mo')
110n/aMMOFILE = os.path.join(LOCALEDIR, 'metadata.mo')
111n/a
112n/a
113n/aclass GettextBaseTest(unittest.TestCase):
114n/a def setUp(self):
115n/a if not os.path.isdir(LOCALEDIR):
116n/a os.makedirs(LOCALEDIR)
117n/a with open(MOFILE, 'wb') as fp:
118n/a fp.write(base64.decodebytes(GNU_MO_DATA))
119n/a with open(MOFILE_BAD_MAJOR_VERSION, 'wb') as fp:
120n/a fp.write(base64.decodebytes(GNU_MO_DATA_BAD_MAJOR_VERSION))
121n/a with open(MOFILE_BAD_MINOR_VERSION, 'wb') as fp:
122n/a fp.write(base64.decodebytes(GNU_MO_DATA_BAD_MINOR_VERSION))
123n/a with open(UMOFILE, 'wb') as fp:
124n/a fp.write(base64.decodebytes(UMO_DATA))
125n/a with open(MMOFILE, 'wb') as fp:
126n/a fp.write(base64.decodebytes(MMO_DATA))
127n/a self.env = support.EnvironmentVarGuard()
128n/a self.env['LANGUAGE'] = 'xx'
129n/a gettext._translations.clear()
130n/a
131n/a def tearDown(self):
132n/a self.env.__exit__()
133n/a del self.env
134n/a support.rmtree(os.path.split(LOCALEDIR)[0])
135n/a
136n/aGNU_MO_DATA_ISSUE_17898 = b'''\
137n/a3hIElQAAAAABAAAAHAAAACQAAAAAAAAAAAAAAAAAAAAsAAAAggAAAC0AAAAAUGx1cmFsLUZvcm1z
138n/aOiBucGx1cmFscz0yOyBwbHVyYWw9KG4gIT0gMSk7CiMtIy0jLSMtIyAgbWVzc2FnZXMucG8gKEVk
139n/aWCBTdHVkaW8pICAjLSMtIy0jLSMKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PVVU
140n/aRi04CgA=
141n/a'''
142n/a
143n/aclass GettextTestCase1(GettextBaseTest):
144n/a def setUp(self):
145n/a GettextBaseTest.setUp(self)
146n/a self.localedir = os.curdir
147n/a self.mofile = MOFILE
148n/a gettext.install('gettext', self.localedir)
149n/a
150n/a def test_some_translations(self):
151n/a eq = self.assertEqual
152n/a # test some translations
153n/a eq(_('albatross'), 'albatross')
154n/a eq(_('mullusk'), 'bacon')
155n/a eq(_(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove')
156n/a eq(_(r'nudge nudge'), 'wink wink')
157n/a
158n/a def test_double_quotes(self):
159n/a eq = self.assertEqual
160n/a # double quotes
161n/a eq(_("albatross"), 'albatross')
162n/a eq(_("mullusk"), 'bacon')
163n/a eq(_(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove')
164n/a eq(_(r"nudge nudge"), 'wink wink')
165n/a
166n/a def test_triple_single_quotes(self):
167n/a eq = self.assertEqual
168n/a # triple single quotes
169n/a eq(_('''albatross'''), 'albatross')
170n/a eq(_('''mullusk'''), 'bacon')
171n/a eq(_(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove')
172n/a eq(_(r'''nudge nudge'''), 'wink wink')
173n/a
174n/a def test_triple_double_quotes(self):
175n/a eq = self.assertEqual
176n/a # triple double quotes
177n/a eq(_("""albatross"""), 'albatross')
178n/a eq(_("""mullusk"""), 'bacon')
179n/a eq(_(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove')
180n/a eq(_(r"""nudge nudge"""), 'wink wink')
181n/a
182n/a def test_multiline_strings(self):
183n/a eq = self.assertEqual
184n/a # multiline strings
185n/a eq(_('''This module provides internationalization and localization
186n/asupport for your Python programs by providing an interface to the GNU
187n/agettext message catalog library.'''),
188n/a '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba
189n/afhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH
190n/atrggrkg zrffntr pngnybt yvoenel.''')
191n/a
192n/a def test_the_alternative_interface(self):
193n/a eq = self.assertEqual
194n/a # test the alternative interface
195n/a with open(self.mofile, 'rb') as fp:
196n/a t = gettext.GNUTranslations(fp)
197n/a # Install the translation object
198n/a t.install()
199n/a eq(_('nudge nudge'), 'wink wink')
200n/a # Try unicode return type
201n/a t.install()
202n/a eq(_('mullusk'), 'bacon')
203n/a # Test installation of other methods
204n/a import builtins
205n/a t.install(names=["gettext", "lgettext"])
206n/a eq(_, t.gettext)
207n/a eq(builtins.gettext, t.gettext)
208n/a eq(lgettext, t.lgettext)
209n/a del builtins.gettext
210n/a del builtins.lgettext
211n/a
212n/a
213n/aclass GettextTestCase2(GettextBaseTest):
214n/a def setUp(self):
215n/a GettextBaseTest.setUp(self)
216n/a self.localedir = os.curdir
217n/a # Set up the bindings
218n/a gettext.bindtextdomain('gettext', self.localedir)
219n/a gettext.textdomain('gettext')
220n/a # For convenience
221n/a self._ = gettext.gettext
222n/a
223n/a def test_bindtextdomain(self):
224n/a self.assertEqual(gettext.bindtextdomain('gettext'), self.localedir)
225n/a
226n/a def test_textdomain(self):
227n/a self.assertEqual(gettext.textdomain(), 'gettext')
228n/a
229n/a def test_bad_major_version(self):
230n/a with open(MOFILE_BAD_MAJOR_VERSION, 'rb') as fp:
231n/a with self.assertRaises(OSError) as cm:
232n/a gettext.GNUTranslations(fp)
233n/a
234n/a exception = cm.exception
235n/a self.assertEqual(exception.errno, 0)
236n/a self.assertEqual(exception.strerror, "Bad version number 5")
237n/a self.assertEqual(exception.filename, MOFILE_BAD_MAJOR_VERSION)
238n/a
239n/a def test_bad_minor_version(self):
240n/a with open(MOFILE_BAD_MINOR_VERSION, 'rb') as fp:
241n/a # Check that no error is thrown with a bad minor version number
242n/a gettext.GNUTranslations(fp)
243n/a
244n/a def test_some_translations(self):
245n/a eq = self.assertEqual
246n/a # test some translations
247n/a eq(self._('albatross'), 'albatross')
248n/a eq(self._('mullusk'), 'bacon')
249n/a eq(self._(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove')
250n/a eq(self._(r'nudge nudge'), 'wink wink')
251n/a
252n/a def test_double_quotes(self):
253n/a eq = self.assertEqual
254n/a # double quotes
255n/a eq(self._("albatross"), 'albatross')
256n/a eq(self._("mullusk"), 'bacon')
257n/a eq(self._(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove')
258n/a eq(self._(r"nudge nudge"), 'wink wink')
259n/a
260n/a def test_triple_single_quotes(self):
261n/a eq = self.assertEqual
262n/a # triple single quotes
263n/a eq(self._('''albatross'''), 'albatross')
264n/a eq(self._('''mullusk'''), 'bacon')
265n/a eq(self._(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove')
266n/a eq(self._(r'''nudge nudge'''), 'wink wink')
267n/a
268n/a def test_triple_double_quotes(self):
269n/a eq = self.assertEqual
270n/a # triple double quotes
271n/a eq(self._("""albatross"""), 'albatross')
272n/a eq(self._("""mullusk"""), 'bacon')
273n/a eq(self._(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove')
274n/a eq(self._(r"""nudge nudge"""), 'wink wink')
275n/a
276n/a def test_multiline_strings(self):
277n/a eq = self.assertEqual
278n/a # multiline strings
279n/a eq(self._('''This module provides internationalization and localization
280n/asupport for your Python programs by providing an interface to the GNU
281n/agettext message catalog library.'''),
282n/a '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba
283n/afhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH
284n/atrggrkg zrffntr pngnybt yvoenel.''')
285n/a
286n/a
287n/aclass PluralFormsTestCase(GettextBaseTest):
288n/a def setUp(self):
289n/a GettextBaseTest.setUp(self)
290n/a self.mofile = MOFILE
291n/a
292n/a def test_plural_forms1(self):
293n/a eq = self.assertEqual
294n/a x = gettext.ngettext('There is %s file', 'There are %s files', 1)
295n/a eq(x, 'Hay %s fichero')
296n/a x = gettext.ngettext('There is %s file', 'There are %s files', 2)
297n/a eq(x, 'Hay %s ficheros')
298n/a
299n/a def test_plural_forms2(self):
300n/a eq = self.assertEqual
301n/a with open(self.mofile, 'rb') as fp:
302n/a t = gettext.GNUTranslations(fp)
303n/a x = t.ngettext('There is %s file', 'There are %s files', 1)
304n/a eq(x, 'Hay %s fichero')
305n/a x = t.ngettext('There is %s file', 'There are %s files', 2)
306n/a eq(x, 'Hay %s ficheros')
307n/a
308n/a # Examples from http://www.gnu.org/software/gettext/manual/gettext.html
309n/a
310n/a def test_ja(self):
311n/a eq = self.assertEqual
312n/a f = gettext.c2py('0')
313n/a s = ''.join([ str(f(x)) for x in range(200) ])
314n/a eq(s, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
315n/a
316n/a def test_de(self):
317n/a eq = self.assertEqual
318n/a f = gettext.c2py('n != 1')
319n/a s = ''.join([ str(f(x)) for x in range(200) ])
320n/a eq(s, "10111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
321n/a
322n/a def test_fr(self):
323n/a eq = self.assertEqual
324n/a f = gettext.c2py('n>1')
325n/a s = ''.join([ str(f(x)) for x in range(200) ])
326n/a eq(s, "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
327n/a
328n/a def test_lv(self):
329n/a eq = self.assertEqual
330n/a f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2')
331n/a s = ''.join([ str(f(x)) for x in range(200) ])
332n/a eq(s, "20111111111111111111101111111110111111111011111111101111111110111111111011111111101111111110111111111011111111111111111110111111111011111111101111111110111111111011111111101111111110111111111011111111")
333n/a
334n/a def test_gd(self):
335n/a eq = self.assertEqual
336n/a f = gettext.c2py('n==1 ? 0 : n==2 ? 1 : 2')
337n/a s = ''.join([ str(f(x)) for x in range(200) ])
338n/a eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
339n/a
340n/a def test_gd2(self):
341n/a eq = self.assertEqual
342n/a # Tests the combination of parentheses and "?:"
343n/a f = gettext.c2py('n==1 ? 0 : (n==2 ? 1 : 2)')
344n/a s = ''.join([ str(f(x)) for x in range(200) ])
345n/a eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
346n/a
347n/a def test_ro(self):
348n/a eq = self.assertEqual
349n/a f = gettext.c2py('n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2')
350n/a s = ''.join([ str(f(x)) for x in range(200) ])
351n/a eq(s, "10111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222")
352n/a
353n/a def test_lt(self):
354n/a eq = self.assertEqual
355n/a f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2')
356n/a s = ''.join([ str(f(x)) for x in range(200) ])
357n/a eq(s, "20111111112222222222201111111120111111112011111111201111111120111111112011111111201111111120111111112011111111222222222220111111112011111111201111111120111111112011111111201111111120111111112011111111")
358n/a
359n/a def test_ru(self):
360n/a eq = self.assertEqual
361n/a f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2')
362n/a s = ''.join([ str(f(x)) for x in range(200) ])
363n/a eq(s, "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222")
364n/a
365n/a def test_cs(self):
366n/a eq = self.assertEqual
367n/a f = gettext.c2py('(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2')
368n/a s = ''.join([ str(f(x)) for x in range(200) ])
369n/a eq(s, "20111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
370n/a
371n/a def test_pl(self):
372n/a eq = self.assertEqual
373n/a f = gettext.c2py('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2')
374n/a s = ''.join([ str(f(x)) for x in range(200) ])
375n/a eq(s, "20111222222222222222221112222222111222222211122222221112222222111222222211122222221112222222111222222211122222222222222222111222222211122222221112222222111222222211122222221112222222111222222211122222")
376n/a
377n/a def test_sl(self):
378n/a eq = self.assertEqual
379n/a f = gettext.c2py('n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3')
380n/a s = ''.join([ str(f(x)) for x in range(200) ])
381n/a eq(s, "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333")
382n/a
383n/a def test_ar(self):
384n/a eq = self.assertEqual
385n/a f = gettext.c2py('n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5')
386n/a s = ''.join([ str(f(x)) for x in range(200) ])
387n/a eq(s, "01233333333444444444444444444444444444444444444444444444444444444444444444444444444444444444444444445553333333344444444444444444444444444444444444444444444444444444444444444444444444444444444444444444")
388n/a
389n/a def test_security(self):
390n/a raises = self.assertRaises
391n/a # Test for a dangerous expression
392n/a raises(ValueError, gettext.c2py, "os.chmod('/etc/passwd',0777)")
393n/a # issue28563
394n/a raises(ValueError, gettext.c2py, '"(eval(foo) && ""')
395n/a raises(ValueError, gettext.c2py, 'f"{os.system(\'sh\')}"')
396n/a # Maximum recursion depth exceeded during compilation
397n/a raises(ValueError, gettext.c2py, 'n+'*10000 + 'n')
398n/a self.assertEqual(gettext.c2py('n+'*100 + 'n')(1), 101)
399n/a # MemoryError during compilation
400n/a raises(ValueError, gettext.c2py, '('*100 + 'n' + ')'*100)
401n/a # Maximum recursion depth exceeded in C to Python translator
402n/a raises(ValueError, gettext.c2py, '('*10000 + 'n' + ')'*10000)
403n/a self.assertEqual(gettext.c2py('('*20 + 'n' + ')'*20)(1), 1)
404n/a
405n/a def test_chained_comparison(self):
406n/a # C doesn't chain comparison as Python so 2 == 2 == 2 gets different results
407n/a f = gettext.c2py('n == n == n')
408n/a self.assertEqual(''.join(str(f(x)) for x in range(3)), '010')
409n/a f = gettext.c2py('1 < n == n')
410n/a self.assertEqual(''.join(str(f(x)) for x in range(3)), '100')
411n/a f = gettext.c2py('n == n < 2')
412n/a self.assertEqual(''.join(str(f(x)) for x in range(3)), '010')
413n/a f = gettext.c2py('0 < n < 2')
414n/a self.assertEqual(''.join(str(f(x)) for x in range(3)), '111')
415n/a
416n/a def test_decimal_number(self):
417n/a self.assertEqual(gettext.c2py('0123')(1), 123)
418n/a
419n/a def test_invalid_syntax(self):
420n/a invalid_expressions = [
421n/a 'x>1', '(n>1', 'n>1)', '42**42**42', '0xa', '1.0', '1e2',
422n/a 'n>0x1', '+n', '-n', 'n()', 'n(1)', '1+', 'nn', 'n n',
423n/a ]
424n/a for expr in invalid_expressions:
425n/a with self.assertRaises(ValueError):
426n/a gettext.c2py(expr)
427n/a
428n/a def test_nested_condition_operator(self):
429n/a self.assertEqual(gettext.c2py('n?1?2:3:4')(0), 4)
430n/a self.assertEqual(gettext.c2py('n?1?2:3:4')(1), 2)
431n/a self.assertEqual(gettext.c2py('n?1:3?4:5')(0), 4)
432n/a self.assertEqual(gettext.c2py('n?1:3?4:5')(1), 1)
433n/a
434n/a def test_division(self):
435n/a f = gettext.c2py('2/n*3')
436n/a self.assertEqual(f(1), 6)
437n/a self.assertEqual(f(2), 3)
438n/a self.assertEqual(f(3), 0)
439n/a self.assertEqual(f(-1), -6)
440n/a self.assertRaises(ZeroDivisionError, f, 0)
441n/a
442n/a def test_plural_number(self):
443n/a f = gettext.c2py('n != 1')
444n/a self.assertEqual(f(1), 0)
445n/a self.assertEqual(f(2), 1)
446n/a self.assertEqual(f(1.0), 0)
447n/a self.assertEqual(f(2.0), 1)
448n/a self.assertEqual(f(1.1), 1)
449n/a self.assertRaises(TypeError, f, '2')
450n/a self.assertRaises(TypeError, f, b'2')
451n/a self.assertRaises(TypeError, f, [])
452n/a self.assertRaises(TypeError, f, object())
453n/a
454n/a
455n/aclass GNUTranslationParsingTest(GettextBaseTest):
456n/a def test_plural_form_error_issue17898(self):
457n/a with open(MOFILE, 'wb') as fp:
458n/a fp.write(base64.decodebytes(GNU_MO_DATA_ISSUE_17898))
459n/a with open(MOFILE, 'rb') as fp:
460n/a # If this runs cleanly, the bug is fixed.
461n/a t = gettext.GNUTranslations(fp)
462n/a
463n/a
464n/aclass UnicodeTranslationsTest(GettextBaseTest):
465n/a def setUp(self):
466n/a GettextBaseTest.setUp(self)
467n/a with open(UMOFILE, 'rb') as fp:
468n/a self.t = gettext.GNUTranslations(fp)
469n/a self._ = self.t.gettext
470n/a
471n/a def test_unicode_msgid(self):
472n/a unless = self.assertTrue
473n/a unless(isinstance(self._(''), str))
474n/a unless(isinstance(self._(''), str))
475n/a
476n/a def test_unicode_msgstr(self):
477n/a eq = self.assertEqual
478n/a eq(self._('ab\xde'), '\xa4yz')
479n/a
480n/a
481n/aclass WeirdMetadataTest(GettextBaseTest):
482n/a def setUp(self):
483n/a GettextBaseTest.setUp(self)
484n/a with open(MMOFILE, 'rb') as fp:
485n/a try:
486n/a self.t = gettext.GNUTranslations(fp)
487n/a except:
488n/a self.tearDown()
489n/a raise
490n/a
491n/a def test_weird_metadata(self):
492n/a info = self.t.info()
493n/a self.assertEqual(len(info), 9)
494n/a self.assertEqual(info['last-translator'],
495n/a 'John Doe <jdoe@example.com>\nJane Foobar <jfoobar@example.com>')
496n/a
497n/a
498n/aclass DummyGNUTranslations(gettext.GNUTranslations):
499n/a def foo(self):
500n/a return 'foo'
501n/a
502n/a
503n/aclass GettextCacheTestCase(GettextBaseTest):
504n/a def test_cache(self):
505n/a self.localedir = os.curdir
506n/a self.mofile = MOFILE
507n/a
508n/a self.assertEqual(len(gettext._translations), 0)
509n/a
510n/a t = gettext.translation('gettext', self.localedir)
511n/a
512n/a self.assertEqual(len(gettext._translations), 1)
513n/a
514n/a t = gettext.translation('gettext', self.localedir,
515n/a class_=DummyGNUTranslations)
516n/a
517n/a self.assertEqual(len(gettext._translations), 2)
518n/a self.assertEqual(t.__class__, DummyGNUTranslations)
519n/a
520n/a # Calling it again doesn't add to the cache
521n/a
522n/a t = gettext.translation('gettext', self.localedir,
523n/a class_=DummyGNUTranslations)
524n/a
525n/a self.assertEqual(len(gettext._translations), 2)
526n/a self.assertEqual(t.__class__, DummyGNUTranslations)
527n/a
528n/a
529n/aclass MiscTestCase(unittest.TestCase):
530n/a def test__all__(self):
531n/a blacklist = {'c2py', 'ENOENT'}
532n/a support.check__all__(self, gettext, blacklist=blacklist)
533n/a
534n/a
535n/adef test_main():
536n/a support.run_unittest(__name__)
537n/a
538n/aif __name__ == '__main__':
539n/a test_main()
540n/a
541n/a
542n/a# For reference, here's the .po file used to created the GNU_MO_DATA above.
543n/a#
544n/a# The original version was automatically generated from the sources with
545n/a# pygettext. Later it was manually modified to add plural forms support.
546n/a
547n/a'''
548n/a# Dummy translation for the Python test_gettext.py module.
549n/a# Copyright (C) 2001 Python Software Foundation
550n/a# Barry Warsaw <barry@python.org>, 2000.
551n/a#
552n/amsgid ""
553n/amsgstr ""
554n/a"Project-Id-Version: 2.0\n"
555n/a"PO-Revision-Date: 2003-04-11 14:32-0400\n"
556n/a"Last-Translator: J. David Ibanez <j-david@noos.fr>\n"
557n/a"Language-Team: XX <python-dev@python.org>\n"
558n/a"MIME-Version: 1.0\n"
559n/a"Content-Type: text/plain; charset=iso-8859-1\n"
560n/a"Content-Transfer-Encoding: 8bit\n"
561n/a"Generated-By: pygettext.py 1.1\n"
562n/a"Plural-Forms: nplurals=2; plural=n!=1;\n"
563n/a
564n/a#: test_gettext.py:19 test_gettext.py:25 test_gettext.py:31 test_gettext.py:37
565n/a#: test_gettext.py:51 test_gettext.py:80 test_gettext.py:86 test_gettext.py:92
566n/a#: test_gettext.py:98
567n/amsgid "nudge nudge"
568n/amsgstr "wink wink"
569n/a
570n/a#: test_gettext.py:16 test_gettext.py:22 test_gettext.py:28 test_gettext.py:34
571n/a#: test_gettext.py:77 test_gettext.py:83 test_gettext.py:89 test_gettext.py:95
572n/amsgid "albatross"
573n/amsgstr ""
574n/a
575n/a#: test_gettext.py:18 test_gettext.py:24 test_gettext.py:30 test_gettext.py:36
576n/a#: test_gettext.py:79 test_gettext.py:85 test_gettext.py:91 test_gettext.py:97
577n/amsgid "Raymond Luxury Yach-t"
578n/amsgstr "Throatwobbler Mangrove"
579n/a
580n/a#: test_gettext.py:17 test_gettext.py:23 test_gettext.py:29 test_gettext.py:35
581n/a#: test_gettext.py:56 test_gettext.py:78 test_gettext.py:84 test_gettext.py:90
582n/a#: test_gettext.py:96
583n/amsgid "mullusk"
584n/amsgstr "bacon"
585n/a
586n/a#: test_gettext.py:40 test_gettext.py:101
587n/amsgid ""
588n/a"This module provides internationalization and localization\n"
589n/a"support for your Python programs by providing an interface to the GNU\n"
590n/a"gettext message catalog library."
591n/amsgstr ""
592n/a"Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba\n"
593n/a"fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH\n"
594n/a"trggrkg zrffntr pngnybt yvoenel."
595n/a
596n/a# Manually added, as neither pygettext nor xgettext support plural forms
597n/a# in Python.
598n/amsgid "There is %s file"
599n/amsgid_plural "There are %s files"
600n/amsgstr[0] "Hay %s fichero"
601n/amsgstr[1] "Hay %s ficheros"
602n/a'''
603n/a
604n/a# Here's the second example po file example, used to generate the UMO_DATA
605n/a# containing utf-8 encoded Unicode strings
606n/a
607n/a'''
608n/a# Dummy translation for the Python test_gettext.py module.
609n/a# Copyright (C) 2001 Python Software Foundation
610n/a# Barry Warsaw <barry@python.org>, 2000.
611n/a#
612n/amsgid ""
613n/amsgstr ""
614n/a"Project-Id-Version: 2.0\n"
615n/a"PO-Revision-Date: 2003-04-11 12:42-0400\n"
616n/a"Last-Translator: Barry A. WArsaw <barry@python.org>\n"
617n/a"Language-Team: XX <python-dev@python.org>\n"
618n/a"MIME-Version: 1.0\n"
619n/a"Content-Type: text/plain; charset=utf-8\n"
620n/a"Content-Transfer-Encoding: 7bit\n"
621n/a"Generated-By: manually\n"
622n/a
623n/a#: nofile:0
624n/amsgid "ab\xc3\x9e"
625n/amsgstr "\xc2\xa4yz"
626n/a'''
627n/a
628n/a# Here's the third example po file, used to generate MMO_DATA
629n/a
630n/a'''
631n/amsgid ""
632n/amsgstr ""
633n/a"Project-Id-Version: No Project 0.0\n"
634n/a"POT-Creation-Date: Wed Dec 11 07:44:15 2002\n"
635n/a"PO-Revision-Date: 2002-08-14 01:18:58+00:00\n"
636n/a"Last-Translator: John Doe <jdoe@example.com>\n"
637n/a"Jane Foobar <jfoobar@example.com>\n"
638n/a"Language-Team: xx <xx@example.com>\n"
639n/a"MIME-Version: 1.0\n"
640n/a"Content-Type: text/plain; charset=iso-8859-15\n"
641n/a"Content-Transfer-Encoding: quoted-printable\n"
642n/a"Generated-By: pygettext.py 1.3\n"
643n/a'''
644n/a
645n/a#
646n/a# messages.po, used for bug 17898
647n/a#
648n/a
649n/a'''
650n/a# test file for http://bugs.python.org/issue17898
651n/amsgid ""
652n/amsgstr ""
653n/a"Plural-Forms: nplurals=2; plural=(n != 1);\n"
654n/a"#-#-#-#-# messages.po (EdX Studio) #-#-#-#-#\n"
655n/a"Content-Type: text/plain; charset=UTF-8\n"
656n/a'''