Mercurial > babel > mirror
view babel/messages/tests/pofile.py @ 591:d1618dfaf114 trunk
change Locale comparison: Locales are now considered equal if all of their attributes (language, territory, script, variant) are equal. Before __eq__ used the simple string representation which hides errors in Locale instantiation (see #279 and #311 for more information).
author | fschwarz |
---|---|
date | Thu, 09 Aug 2012 07:36:36 +0000 |
parents | 5c9dba5dd311 |
children |
line wrap: on
line source
# -*- coding: utf-8 -*- # # Copyright (C) 2007-2011 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://babel.edgewall.org/wiki/License. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://babel.edgewall.org/log/. from datetime import datetime import doctest from StringIO import StringIO import unittest from babel.core import Locale from babel.messages.catalog import Catalog, Message from babel.messages import pofile from babel.util import FixedOffsetTimezone class ReadPoTestCase(unittest.TestCase): def test_preserve_locale(self): buf = StringIO(r'''msgid "foo" msgstr "Voh"''') catalog = pofile.read_po(buf, locale='en_US') self.assertEqual(Locale('en', 'US'), catalog.locale) def test_preserve_domain(self): buf = StringIO(r'''msgid "foo" msgstr "Voh"''') catalog = pofile.read_po(buf, domain='mydomain') self.assertEqual('mydomain', catalog.domain) def test_applies_specified_encoding_during_read(self): buf = StringIO(u''' msgid "" msgstr "" "Project-Id-Version: 3.15\\n" "Report-Msgid-Bugs-To: Fliegender Zirkus <fliegender@zirkus.de>\\n" "POT-Creation-Date: 2007-09-27 11:19+0700\\n" "PO-Revision-Date: 2007-09-27 21:42-0700\\n" "Last-Translator: John <cleese@bavaria.de>\\n" "Language-Team: German Lang <de@babel.org>\\n" "Plural-Forms: nplurals=2; plural=(n != 1)\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=iso-8859-1\\n" "Content-Transfer-Encoding: 8bit\\n" "Generated-By: Babel 1.0dev-r313\\n" msgid "foo" msgstr "bär"'''.encode('iso-8859-1')) catalog = pofile.read_po(buf, locale='de_DE') self.assertEqual(u'bär', catalog.get('foo').string) def test_read_multiline(self): buf = StringIO(r'''msgid "" "Here's some text that\n" "includesareallylongwordthatmightbutshouldnt" " throw us into an infinite " "loop\n" msgstr ""''') catalog = pofile.read_po(buf) self.assertEqual(1, len(catalog)) message = list(catalog)[1] self.assertEqual("Here's some text that\nincludesareallylongwordthat" "mightbutshouldnt throw us into an infinite loop\n", message.id) def test_fuzzy_header(self): buf = StringIO(r'''\ # Translations template for AReallyReallyLongNameForAProject. # Copyright (C) 2007 ORGANIZATION # This file is distributed under the same license as the # AReallyReallyLongNameForAProject project. # FIRST AUTHOR <EMAIL@ADDRESS>, 2007. # #, fuzzy ''') catalog = pofile.read_po(buf) self.assertEqual(1, len(list(catalog))) self.assertEqual(True, list(catalog)[0].fuzzy) def test_not_fuzzy_header(self): buf = StringIO(r'''\ # Translations template for AReallyReallyLongNameForAProject. # Copyright (C) 2007 ORGANIZATION # This file is distributed under the same license as the # AReallyReallyLongNameForAProject project. # FIRST AUTHOR <EMAIL@ADDRESS>, 2007. # ''') catalog = pofile.read_po(buf) self.assertEqual(1, len(list(catalog))) self.assertEqual(False, list(catalog)[0].fuzzy) def test_header_entry(self): buf = StringIO(r'''\ # SOME DESCRIPTIVE TITLE. # Copyright (C) 2007 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, 2007. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: 3.15\n" "Report-Msgid-Bugs-To: Fliegender Zirkus <fliegender@zirkus.de>\n" "POT-Creation-Date: 2007-09-27 11:19+0700\n" "PO-Revision-Date: 2007-09-27 21:42-0700\n" "Last-Translator: John <cleese@bavaria.de>\n" "Language-Team: German Lang <de@babel.org>\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-2\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.0dev-r313\n" ''') catalog = pofile.read_po(buf) self.assertEqual(1, len(list(catalog))) self.assertEqual(u'3.15', catalog.version) self.assertEqual(u'Fliegender Zirkus <fliegender@zirkus.de>', catalog.msgid_bugs_address) self.assertEqual(datetime(2007, 9, 27, 11, 19, tzinfo=FixedOffsetTimezone(7 * 60)), catalog.creation_date) self.assertEqual(u'John <cleese@bavaria.de>', catalog.last_translator) self.assertEqual(u'German Lang <de@babel.org>', catalog.language_team) self.assertEqual(u'iso-8859-2', catalog.charset) self.assertEqual(True, list(catalog)[0].fuzzy) def test_obsolete_message(self): buf = StringIO(r'''# This is an obsolete message #~ msgid "foo" #~ msgstr "Voh" # This message is not obsolete #: main.py:1 msgid "bar" msgstr "Bahr" ''') catalog = pofile.read_po(buf) self.assertEqual(1, len(catalog)) self.assertEqual(1, len(catalog.obsolete)) message = catalog.obsolete[u'foo'] self.assertEqual(u'foo', message.id) self.assertEqual(u'Voh', message.string) self.assertEqual(['This is an obsolete message'], message.user_comments) def test_obsolete_message_ignored(self): buf = StringIO(r'''# This is an obsolete message #~ msgid "foo" #~ msgstr "Voh" # This message is not obsolete #: main.py:1 msgid "bar" msgstr "Bahr" ''') catalog = pofile.read_po(buf, ignore_obsolete=True) self.assertEqual(1, len(catalog)) self.assertEqual(0, len(catalog.obsolete)) def test_with_context(self): buf = StringIO(r'''# Some string in the menu #: main.py:1 msgctxt "Menu" msgid "foo" msgstr "Voh" # Another string in the menu #: main.py:2 msgctxt "Menu" msgid "bar" msgstr "Bahr" ''') catalog = pofile.read_po(buf, ignore_obsolete=True) self.assertEqual(2, len(catalog)) message = catalog.get('foo', context='Menu') self.assertEqual('Menu', message.context) message = catalog.get('bar', context='Menu') self.assertEqual('Menu', message.context) # And verify it pass through write_po out_buf = StringIO() pofile.write_po(out_buf, catalog, omit_header=True) assert out_buf.getvalue().strip() == buf.getvalue().strip(), \ out_buf.getvalue() def test_with_context_two(self): buf = StringIO(r'''msgctxt "Menu" msgid "foo" msgstr "Voh" msgctxt "Mannu" msgid "bar" msgstr "Bahr" ''') catalog = pofile.read_po(buf, ignore_obsolete=True) self.assertEqual(2, len(catalog)) message = catalog.get('foo', context='Menu') self.assertEqual('Menu', message.context) message = catalog.get('bar', context='Mannu') self.assertEqual('Mannu', message.context) # And verify it pass through write_po out_buf = StringIO() pofile.write_po(out_buf, catalog, omit_header=True) assert out_buf.getvalue().strip() == buf.getvalue().strip(), out_buf.getvalue() def test_single_plural_form(self): buf = StringIO(r'''msgid "foo" msgid_plural "foos" msgstr[0] "Voh"''') catalog = pofile.read_po(buf, locale='ja_JP') self.assertEqual(1, len(catalog)) self.assertEqual(1, catalog.num_plurals) message = catalog['foo'] self.assertEqual(1, len(message.string)) def test_singular_plural_form(self): buf = StringIO(r'''msgid "foo" msgid_plural "foos" msgstr[0] "Voh" msgstr[1] "Vohs"''') catalog = pofile.read_po(buf, locale='nl_NL') self.assertEqual(1, len(catalog)) self.assertEqual(2, catalog.num_plurals) message = catalog['foo'] self.assertEqual(2, len(message.string)) def test_more_than_two_plural_forms(self): buf = StringIO(r'''msgid "foo" msgid_plural "foos" msgstr[0] "Voh" msgstr[1] "Vohs" msgstr[2] "Vohss"''') catalog = pofile.read_po(buf, locale='lv_LV') self.assertEqual(1, len(catalog)) self.assertEqual(3, catalog.num_plurals) message = catalog['foo'] self.assertEqual(3, len(message.string)) self.assertEqual(u'Vohss', message.string[2]) def test_plural_with_square_brackets(self): buf = StringIO(r'''msgid "foo" msgid_plural "foos" msgstr[0] "Voh [text]" msgstr[1] "Vohs [text]"''') catalog = pofile.read_po(buf, locale='nb_NO') self.assertEqual(1, len(catalog)) self.assertEqual(2, catalog.num_plurals) message = catalog['foo'] self.assertEqual(2, len(message.string)) class WritePoTestCase(unittest.TestCase): def test_join_locations(self): catalog = Catalog() catalog.add(u'foo', locations=[('main.py', 1)]) catalog.add(u'foo', locations=[('utils.py', 3)]) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual('''#: main.py:1 utils.py:3 msgid "foo" msgstr ""''', buf.getvalue().strip()) def test_write_po_file_with_specified_charset(self): catalog = Catalog(charset='iso-8859-1') catalog.add('foo', u'äöü', locations=[('main.py', 1)]) buf = StringIO() pofile.write_po(buf, catalog, omit_header=False) po_file = buf.getvalue().strip() assert r'"Content-Type: text/plain; charset=iso-8859-1\n"' in po_file assert u'msgstr "äöü"'.encode('iso-8859-1') in po_file def test_duplicate_comments(self): catalog = Catalog() catalog.add(u'foo', auto_comments=['A comment']) catalog.add(u'foo', auto_comments=['A comment']) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual('''#. A comment msgid "foo" msgstr ""''', buf.getvalue().strip()) def test_wrap_long_lines(self): text = """Here's some text where white space and line breaks matter, and should not be removed """ catalog = Catalog() catalog.add(text, locations=[('main.py', 1)]) buf = StringIO() pofile.write_po(buf, catalog, no_location=True, omit_header=True, width=42) self.assertEqual(r'''msgid "" "Here's some text where \n" "white space and line breaks matter, and" " should\n" "\n" "not be removed\n" "\n" msgstr ""''', buf.getvalue().strip()) def test_wrap_long_lines_with_long_word(self): text = """Here's some text that includesareallylongwordthatmightbutshouldnt throw us into an infinite loop """ catalog = Catalog() catalog.add(text, locations=[('main.py', 1)]) buf = StringIO() pofile.write_po(buf, catalog, no_location=True, omit_header=True, width=32) self.assertEqual(r'''msgid "" "Here's some text that\n" "includesareallylongwordthatmightbutshouldnt" " throw us into an infinite " "loop\n" msgstr ""''', buf.getvalue().strip()) def test_wrap_long_lines_in_header(self): """ Verify that long lines in the header comment are wrapped correctly. """ catalog = Catalog(project='AReallyReallyLongNameForAProject', revision_date=datetime(2007, 4, 1)) buf = StringIO() pofile.write_po(buf, catalog) self.assertEqual('''\ # Translations template for AReallyReallyLongNameForAProject. # Copyright (C) 2007 ORGANIZATION # This file is distributed under the same license as the # AReallyReallyLongNameForAProject project. # FIRST AUTHOR <EMAIL@ADDRESS>, 2007. # #, fuzzy''', '\n'.join(buf.getvalue().splitlines()[:7])) def test_wrap_locations_with_hyphens(self): catalog = Catalog() catalog.add(u'foo', locations=[ ('doupy/templates/base/navmenu.inc.html.py', 60) ]) catalog.add(u'foo', locations=[ ('doupy/templates/job-offers/helpers.html', 22) ]) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual('''#: doupy/templates/base/navmenu.inc.html.py:60 #: doupy/templates/job-offers/helpers.html:22 msgid "foo" msgstr ""''', buf.getvalue().strip()) def test_no_wrap_and_width_behaviour_on_comments(self): catalog = Catalog() catalog.add("Pretty dam long message id, which must really be big " "to test this wrap behaviour, if not it won't work.", locations=[("fake.py", n) for n in range(1, 30)]) buf = StringIO() pofile.write_po(buf, catalog, width=None, omit_header=True) self.assertEqual("""\ #: fake.py:1 fake.py:2 fake.py:3 fake.py:4 fake.py:5 fake.py:6 fake.py:7 #: fake.py:8 fake.py:9 fake.py:10 fake.py:11 fake.py:12 fake.py:13 fake.py:14 #: fake.py:15 fake.py:16 fake.py:17 fake.py:18 fake.py:19 fake.py:20 fake.py:21 #: fake.py:22 fake.py:23 fake.py:24 fake.py:25 fake.py:26 fake.py:27 fake.py:28 #: fake.py:29 msgid "pretty dam long message id, which must really be big to test this wrap behaviour, if not it won't work." msgstr "" """, buf.getvalue().lower()) buf = StringIO() pofile.write_po(buf, catalog, width=100, omit_header=True) self.assertEqual("""\ #: fake.py:1 fake.py:2 fake.py:3 fake.py:4 fake.py:5 fake.py:6 fake.py:7 fake.py:8 fake.py:9 fake.py:10 #: fake.py:11 fake.py:12 fake.py:13 fake.py:14 fake.py:15 fake.py:16 fake.py:17 fake.py:18 fake.py:19 #: fake.py:20 fake.py:21 fake.py:22 fake.py:23 fake.py:24 fake.py:25 fake.py:26 fake.py:27 fake.py:28 #: fake.py:29 msgid "" "pretty dam long message id, which must really be big to test this wrap behaviour, if not it won't" " work." msgstr "" """, buf.getvalue().lower()) def test_pot_with_translator_comments(self): catalog = Catalog() catalog.add(u'foo', locations=[('main.py', 1)], auto_comments=['Comment About `foo`']) catalog.add(u'bar', locations=[('utils.py', 3)], user_comments=['Comment About `bar` with', 'multiple lines.']) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual('''#. Comment About `foo` #: main.py:1 msgid "foo" msgstr "" # Comment About `bar` with # multiple lines. #: utils.py:3 msgid "bar" msgstr ""''', buf.getvalue().strip()) def test_po_with_obsolete_message(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)]) catalog.obsolete['bar'] = Message(u'bar', u'Bahr', locations=[('utils.py', 3)], user_comments=['User comment']) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual('''#: main.py:1 msgid "foo" msgstr "Voh" # User comment #~ msgid "bar" #~ msgstr "Bahr"''', buf.getvalue().strip()) def test_po_with_multiline_obsolete_message(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)]) msgid = r"""Here's a message that covers multiple lines, and should still be handled correctly. """ msgstr = r"""Here's a message that covers multiple lines, and should still be handled correctly. """ catalog.obsolete[msgid] = Message(msgid, msgstr, locations=[('utils.py', 3)]) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual(r'''#: main.py:1 msgid "foo" msgstr "Voh" #~ msgid "" #~ "Here's a message that covers\n" #~ "multiple lines, and should still be handled\n" #~ "correctly.\n" #~ msgstr "" #~ "Here's a message that covers\n" #~ "multiple lines, and should still be handled\n" #~ "correctly.\n"''', buf.getvalue().strip()) def test_po_with_obsolete_message_ignored(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)]) catalog.obsolete['bar'] = Message(u'bar', u'Bahr', locations=[('utils.py', 3)], user_comments=['User comment']) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True, ignore_obsolete=True) self.assertEqual('''#: main.py:1 msgid "foo" msgstr "Voh"''', buf.getvalue().strip()) def test_po_with_previous_msgid(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)], previous_id=u'fo') buf = StringIO() pofile.write_po(buf, catalog, omit_header=True, include_previous=True) self.assertEqual('''#: main.py:1 #| msgid "fo" msgid "foo" msgstr "Voh"''', buf.getvalue().strip()) def test_po_with_previous_msgid_plural(self): catalog = Catalog() catalog.add((u'foo', u'foos'), (u'Voh', u'Voeh'), locations=[('main.py', 1)], previous_id=(u'fo', u'fos')) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True, include_previous=True) self.assertEqual('''#: main.py:1 #| msgid "fo" #| msgid_plural "fos" msgid "foo" msgid_plural "foos" msgstr[0] "Voh" msgstr[1] "Voeh"''', buf.getvalue().strip()) def test_sorted_po(self): catalog = Catalog() catalog.add(u'bar', locations=[('utils.py', 3)], user_comments=['Comment About `bar` with', 'multiple lines.']) catalog.add((u'foo', u'foos'), (u'Voh', u'Voeh'), locations=[('main.py', 1)]) buf = StringIO() pofile.write_po(buf, catalog, sort_output=True) value = buf.getvalue().strip() assert '''\ # Comment About `bar` with # multiple lines. #: utils.py:3 msgid "bar" msgstr "" #: main.py:1 msgid "foo" msgid_plural "foos" msgstr[0] "Voh" msgstr[1] "Voeh"''' in value assert value.find('msgid ""') < value.find('msgid "bar"') < value.find('msgid "foo"') def test_silent_location_fallback(self): buf = StringIO('''\ #: broken_file.py msgid "missing line number" msgstr "" #: broken_file.py:broken_line_number msgid "broken line number" msgstr ""''') catalog = pofile.read_po(buf) self.assertEqual(catalog['missing line number'].locations, []) self.assertEqual(catalog['broken line number'].locations, []) class PofileFunctionsTestCase(unittest.TestCase): def test_unescape(self): escaped = u'"Say:\\n \\"hello, world!\\"\\n"' unescaped = u'Say:\n "hello, world!"\n' self.assertNotEqual(unescaped, escaped) self.assertEqual(unescaped, pofile.unescape(escaped)) def test_unescape_of_quoted_newline(self): # regression test for #198 self.assertEqual(r'\n', pofile.unescape(r'"\\n"')) def test_denormalize_on_msgstr_without_empty_first_line(self): # handle irregular multi-line msgstr (no "" as first line) # gracefully (#171) msgstr = '"multi-line\\n"\n" translation"' expected_denormalized = u'multi-line\n translation' self.assertEqual(expected_denormalized, pofile.denormalize(msgstr)) self.assertEqual(expected_denormalized, pofile.denormalize('""\n' + msgstr)) def suite(): suite = unittest.TestSuite() suite.addTest(doctest.DocTestSuite(pofile, optionflags=doctest.ELLIPSIS)) suite.addTest(unittest.makeSuite(ReadPoTestCase)) suite.addTest(unittest.makeSuite(WritePoTestCase)) suite.addTest(unittest.makeSuite(PofileFunctionsTestCase)) return suite if __name__ == '__main__': unittest.main(defaultTest='suite')