diff --git a/polib-0.7.0_dbafdc621bf4.patch b/polib-0.7.0_dbafdc621bf4.patch new file mode 100644 index 0000000..3917fb6 --- /dev/null +++ b/polib-0.7.0_dbafdc621bf4.patch @@ -0,0 +1,261 @@ +diff -r f3b365199366 docs/conf.py +--- a/docs/conf.py Thu Jul 14 14:34:23 2011 +0200 ++++ b/docs/conf.py Tue Nov 01 13:31:57 2011 +1000 +@@ -13,16 +13,18 @@ + + import sys, os + + # If extensions (or modules to document with autodoc) are in another directory, + # add these directories to sys.path here. If the directory is relative to the + # documentation root, use os.path.abspath to make it absolute, like shown here. + sys.path.insert(0, os.path.abspath('..')) + ++import polib ++ + # -- General configuration ----------------------------------------------------- + + # If your documentation needs a minimal Sphinx version, state it here. + #needs_sphinx = '1.0' + + # Add any Sphinx extension module names here, as strings. They can be extensions + # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. + extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] +@@ -43,19 +45,19 @@ master_doc = 'index' + project = u'polib' + copyright = u'2011, David Jean Louis ' + + # The version info for the project you're documenting, acts as replacement for + # |version| and |release|, also used in various other places throughout the + # built documents. + # + # The short X.Y version. +-version = '0.6.0' ++version = polib.__version__ + # The full version, including alpha/beta/rc tags. +-release = '0.6.0' ++release = polib.__version__ + + # The language for content autogenerated by Sphinx. Refer to documentation + # for a list of supported languages. + #language = None + + # There are two options for replacing |today|: either, you set today to some + # non-false value, then it is used: + #today = '' +diff -r f3b365199366 polib.py +--- a/polib.py Thu Jul 14 14:34:23 2011 +0200 ++++ b/polib.py Tue Nov 01 13:31:57 2011 +1000 +@@ -1181,78 +1181,91 @@ class _POFileParser(object): + self.entry_obsolete = 1 + else: + self.entry_obsolete = 0 + + # Take care of keywords like + # msgid, msgid_plural, msgctxt & msgstr. + if tokens[0] in keywords and nb_tokens > 1: + line = line[len(tokens[0]):].lstrip() ++ if re.search(r'([^\\]|^)"', line[1:-1]): ++ raise IOError('Syntax error in po file %s (line %s): '\ ++ 'unescaped double quote found' % \ ++ (self.instance.fpath, i)) + self.current_token = line + self.process(keywords[tokens[0]], i) + continue + + self.current_token = line + + if tokens[0] == '#:' and nb_tokens > 1: + # we are on a occurrences line + self.process('OC', i) + + elif line[:1] == '"': + # we are on a continuation line ++ if re.search(r'([^\\]|^)"', line[1:-1]): ++ raise IOError('Syntax error in po file %s (line %s): '\ ++ 'unescaped double quote found' % \ ++ (self.instance.fpath, i)) + self.process('MC', i) + + elif line[:7] == 'msgstr[': + # we are on a msgstr plural + self.process('MX', i) + +- elif tokens[0] == '#,' and nb_tokens > 1: ++ elif tokens[0] == '#,' and nb_tokens >= 1: + # we are on a flags line + self.process('FL', i) + + elif tokens[0] == '#': + if line == '#': line += ' ' + # we are on a translator comment line + self.process('TC', i) + +- elif tokens[0] == '#.' and nb_tokens > 1: ++ elif tokens[0] == '#.' and nb_tokens >= 1: + # we are on a generated comment line + self.process('GC', i) + + elif tokens[0] == '#|': + if nb_tokens < 2: +- self.process('??', i) +- continue ++ raise IOError('Syntax error in po file %s (line %s)' % \ ++ (self.instance.fpath, i)) + + # Remove the marker and any whitespace right after that. + line = line[2:].lstrip() + self.current_token = line + + if tokens[1].startswith('"'): + # Continuation of previous metadata. + self.process('MC', i) + continue + + if nb_tokens == 2: + # Invalid continuation line. +- self.process('??', i) ++ raise IOError('Syntax error in po file %s (line %s): '\ ++ 'invalid continuation line' % \ ++ (self.instance.fpath, i)) + + # we are on a "previous translation" comment line, + if tokens[1] not in prev_keywords: + # Unknown keyword in previous translation comment. +- self.process('??', i) ++ raise IOError('Syntax error in po file %s (line %s): '\ ++ 'unknown keyword %s' % \ ++ (self.instance.fpath, i, tokens[1])) + + # Remove the keyword and any whitespace + # between it and the starting quote. + line = line[len(tokens[1]):].lstrip() + self.current_token = line + self.process(prev_keywords[tokens[1]], i) + + else: +- self.process('??', i) ++ raise IOError('Syntax error in po file %s (line %s)' % \ ++ (self.instance.fpath, i)) + + if self.current_entry: + # since entries are added when another entry is found, we must add + # the last entry here (only if there are lines) + self.instance.append(self.current_entry) + # before returning the instance, check if there's metadata and if + # so extract it in a dict + firstentry = self.instance[0] +diff -r f3b365199366 tests/test_weird_occurrences.po +--- a/tests/test_weird_occurrences.po Thu Jul 14 14:34:23 2011 +0200 ++++ b/tests/test_weird_occurrences.po Tue Nov 01 13:31:57 2011 +1000 +@@ -9,16 +9,23 @@ msgstr "" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "X-Generator: Pootle 1.1.0rc2\n" + "X-Launchpad-Export-Date: 2007-12-03 23:40+0000\n" + "X-Etoys-Domain: etoys\n" + "X-Etoys-SystemVersion: etoys3.0 of 24 February 2008 update 2029\n" + ++#. Test for empty comment lines ++#. ++#, ++#: main.c:117 ++msgid "Override the default prgname" ++msgstr "Override the default prgname" ++ + #: Balloon-Fills,BitmapFillStyle>>addFillStyleMenuItems:hand:from: + msgid "choose new graphic" + msgstr "escolher novo gráfico" + + #: Balloon-Fills,BitmapFillStyle>>addFillStyleMenuItems:hand:from: + msgid "grab new graphic" + msgstr "agarrar novo gráfico" + +diff -r f3b365199366 tests/tests.py +--- a/tests/tests.py Thu Jul 14 14:34:23 2011 +0200 ++++ b/tests/tests.py Tue Nov 01 13:31:57 2011 +1000 +@@ -78,16 +78,84 @@ msgstr "bar" + + def test_pofile_and_mofile7(self): + """ + Test that encoding is ok when encoding is explicitely given. + """ + po = polib.pofile('tests/test_iso-8859-15.po', encoding='iso-8859-15') + self.assertTrue(po.encoding == 'iso-8859-15') + ++ def test_pofile_and_mofile8(self): ++ """ ++ Test that weird occurrences are correctly parsed. ++ """ ++ po = polib.pofile('tests/test_weird_occurrences.po') ++ self.assertEqual(len(po), 46) ++ ++ def test_unescaped_double_quote1(self): ++ """ ++ Test that polib reports an error when unescaped double quote is found. ++ """ ++ data = r''' ++msgid "Some msgid with \"double\" quotes" ++msgid "Some msgstr with "double\" quotes" ++''' ++ try: ++ po = polib.pofile(data) ++ self.fail("Unescaped quote not detected") ++ except IOError, exc: ++ msg = 'Syntax error in po file None (line 3): unescaped double quote found' ++ self.assertEqual(str(exc), msg) ++ ++ def test_unescaped_double_quote2(self): ++ """ ++ Test that polib reports an error when unescaped double quote is found. ++ """ ++ data = r''' ++msgid "Some msgid with \"double\" quotes" ++msgstr "" ++"Some msgstr with "double\" quotes" ++''' ++ try: ++ po = polib.pofile(data) ++ self.fail("Unescaped quote not detected") ++ except IOError, exc: ++ msg = 'Syntax error in po file None (line 4): unescaped double quote found' ++ self.assertEqual(str(exc), msg) ++ ++ def test_unescaped_double_quote3(self): ++ """ ++ Test that polib reports an error when unescaped double quote is found at the beginning of the string. ++ """ ++ data = r''' ++msgid "Some msgid with \"double\" quotes" ++msgid ""Some msgstr with double\" quotes" ++''' ++ try: ++ po = polib.pofile(data) ++ self.fail("Unescaped quote not detected") ++ except IOError, exc: ++ msg = 'Syntax error in po file None (line 3): unescaped double quote found' ++ ++ def test_unescaped_double_quote4(self): ++ """ ++ Test that polib reports an error when unescaped double quote is found at the beginning of the string. ++ """ ++ data = r''' ++msgid "Some msgid with \"double\" quotes" ++msgstr "" ++""Some msgstr with double\" quotes" ++''' ++ try: ++ po = polib.pofile(data) ++ self.fail("Unescaped quote not detected") ++ except IOError, exc: ++ msg = 'Syntax error in po file None (line 4): unescaped double quote found' ++ self.assertEqual(str(exc), msg) ++ + def test_detect_encoding1(self): + """ + Test that given enconding is returned when file has no encoding defined. + """ + self.assertEqual(polib.detect_encoding('tests/test_noencoding.po'), 'utf-8') + + def test_detect_encoding2(self): + """ diff --git a/python-polib.spec b/python-polib.spec index 7355d62..d052ade 100644 --- a/python-polib.spec +++ b/python-polib.spec @@ -4,7 +4,7 @@ Name: python-polib Version: 0.7.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A library to parse and manage gettext catalogs Group: Development/Languages @@ -12,6 +12,7 @@ License: MIT URL: http://bitbucket.org/izi/polib/ Source0: http://bitbucket.org/izi/polib/downloads/polib-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Patch0: polib-%{version}_dbafdc621bf4.patch BuildArch: noarch BuildRequires: python-devel @@ -28,6 +29,7 @@ POFile, MOFile, POEntry and MOEntry for creating new files/entries. %prep %setup -q -n polib-%{version} +%patch0 -p1 -b .%{version}_dbafdc621bf4 %build %{__python} setup.py build @@ -45,6 +47,14 @@ rm -rf $RPM_BUILD_ROOT %{python_sitelib}/* %changelog +* Tue Nov 01 2011 Ding-Yi Chen - 0.7.0-2 +- Update to upstream commit dbafdc621bf4, which include following: + * Add check for unescaped quotes at the beginning of the string + unit tests + * Fixed issue #27 (polib didn't check unescaped double quote) + better error handling + * Fixed typos in previous commit + * Fixed issue #26 IOError when parsing empty comments (thanks Türker Sezer) + * Do not hardcode polib version in doc conf + * Fri Oct 28 2011 Ding-Yi Chen - 0.7.0-1 - Correct URLs - Replace README with README.rst