Hello community,

here is the log from the commit of package python-polib for openSUSE:Factory 
checked in at 2013-02-11 11:12:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-polib (Old)
 and      /work/SRC/openSUSE:Factory/.python-polib.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-polib", Maintainer is ""

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-polib/python-polib.changes        
2012-09-20 15:43:55.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-polib.new/python-polib.changes   
2013-02-11 11:12:27.000000000 +0100
@@ -1,0 +2,14 @@
+Sat Feb  9 18:47:20 UTC 2013 - [email protected]
+
+- Update to 1.0.3
+  * Fixed issue #38: POFile.append() raised a duplicate exception when
+    you tried to add a new entry with the same msgid and a different msgctxt
+    (only when check_for_duplicates option is set to True)
+  * Fixed issue #39: Added __init__.py file for convenience
+  * Fixed issue #41: UnicodeDecodeError when running setup.py build on
+    python3 with C locale
+  * polib is now fully PEP8 compliant
+  * Small improvements: remove unused "typ" var, mproved Makefile, Make sure
+    BaseFile.__contains__ returns a boolean value
+
+-------------------------------------------------------------------

Old:
----
  polib-1.0.1.tar.bz2

New:
----
  polib-1.0.3.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-polib.spec ++++++
--- /var/tmp/diff_new_pack.i4Kq6P/_old  2013-02-11 11:12:40.000000000 +0100
+++ /var/tmp/diff_new_pack.i4Kq6P/_new  2013-02-11 11:12:40.000000000 +0100
@@ -1,8 +1,8 @@
 #
 # spec file for package python-polib
 #
-# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
-# Copyright (c) 2011 LISA GmbH, Bingen, Germany.
+# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2013 LISA GmbH, Bingen, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 
 Name:           python-polib
-Version:        1.0.1
+Version:        1.0.3
 Release:        0
 Url:            http://bitbucket.org/izi/polib/
 Summary:        A library to manipulate gettext files

++++++ polib-1.0.1.tar.bz2 -> polib-1.0.3.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/CHANGELOG new/polib-1.0.3/CHANGELOG
--- old/polib-1.0.1/CHANGELOG   2012-09-11 10:54:22.000000000 +0200
+++ new/polib-1.0.3/CHANGELOG   2013-02-09 13:27:04.000000000 +0100
@@ -2,6 +2,18 @@
 Changelog
 =========
 
+Version 1.0.3 (2013/02/09)
+--------------------------
+ - Fixed issue #38: POFile.append() raised a duplicate exception when you 
tried to add a new entry with the same msgid and a different msgctxt (only when 
check_for_duplicates option is set to True)
+ - Fixed issue #39: Added __init__.py file for convenience
+ - Fixed issue #41: UnicodeDecodeError when running setup.py build on python3 
with C locale
+ - polib is now fully PEP8 compliant
+ - Small improvements: remove unused "typ" var (thanks Rodrigo Silva), mproved 
Makefile, Make sure _BaseFile.__contains__ returns a boolean value
+
+Version 1.0.2 (2012/10/23)
+--------------------------
+ - allow empty comments, flags or occurences lines
+
 Version 1.0.1 (2012/09/11)
 --------------------------
  - speed up POFile.merge method (thanks @encukou)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/PKG-INFO new/polib-1.0.3/PKG-INFO
--- old/polib-1.0.1/PKG-INFO    2012-09-11 10:56:32.000000000 +0200
+++ new/polib-1.0.3/PKG-INFO    2013-02-09 19:16:02.000000000 +0100
@@ -1,12 +1,12 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: polib
-Version: 1.0.1
+Version: 1.0.3
 Summary: A library to manipulate gettext files (po and mo files).
 Home-page: http://bitbucket.org/izi/polib/
 Author: David Jean Louis
 Author-email: <[email protected]>
 License: MIT
-Download-URL: http://bitbucket.org/izi/polib/downloads/polib-1.0.1.tar.gz
+Download-URL: http://bitbucket.org/izi/polib/downloads/polib-1.0.3.tar.gz
 Description: 
         .. contents:: Table of Contents
         
@@ -38,6 +38,18 @@
         Changelog
         =========
         
+        Version 1.0.3 (2013/02/09)
+        --------------------------
+         - Fixed issue #38: POFile.append() raised a duplicate exception when 
you tried to add a new entry with the same msgid and a different msgctxt (only 
when check_for_duplicates option is set to True)
+         - Fixed issue #39: Added __init__.py file for convenience
+         - Fixed issue #41: UnicodeDecodeError when running setup.py build on 
python3 with C locale
+         - polib is now fully PEP8 compliant
+         - Small improvements: remove unused "typ" var (thanks Rodrigo Silva), 
mproved Makefile, Make sure _BaseFile.__contains__ returns a boolean value
+        
+        Version 1.0.2 (2012/10/23)
+        --------------------------
+         - allow empty comments, flags or occurences lines
+        
         Version 1.0.1 (2012/09/11)
         --------------------------
          - speed up POFile.merge method (thanks @encukou)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/__init__.py new/polib-1.0.3/__init__.py
--- old/polib-1.0.1/__init__.py 1970-01-01 01:00:00.000000000 +0100
+++ new/polib-1.0.3/__init__.py 2012-12-06 11:22:45.000000000 +0100
@@ -0,0 +1,5 @@
+# This __init__.py is only here for convenience, for projects that include a
+# version of polib as a mercurial sub-repository for example.
+#
+# This file will NOT be installed when installing polib with pip, setuptools,
+# or any other mecanism based on the setup.py file.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/polib.py new/polib-1.0.3/polib.py
--- old/polib-1.0.1/polib.py    2012-09-11 10:47:55.000000000 +0200
+++ new/polib-1.0.3/polib.py    2013-02-09 19:09:48.000000000 +0100
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -* coding: utf-8 -*-
 #
 # License: MIT (see LICENSE file provided)
 # vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4:
@@ -12,10 +12,10 @@
 :func:`~polib.mofile` convenience functions.
 """
 
-__author__    = 'David Jean Louis <[email protected]>'
-__version__   = '1.0.1'
-__all__       = ['pofile', 'POFile', 'POEntry', 'mofile', 'MOFile', 'MOEntry',
-                 'detect_encoding', 'escape', 'unescape', 'detect_encoding',]
+__author__ = 'David Jean Louis <[email protected]>'
+__version__ = '1.0.3'
+__all__ = ['pofile', 'POFile', 'POEntry', 'mofile', 'MOFile', 'MOEntry',
+           'default_encoding', 'escape', 'unescape', 'detect_encoding', ]
 
 import array
 import codecs
@@ -25,11 +25,13 @@
 import sys
 import textwrap
 
+
 # the default encoding to use when encoding cannot be detected
 default_encoding = 'utf-8'
 
 # python 2/3 compatibility helpers {{{
 
+
 if sys.version_info[:2] < (3, 0):
     PY3 = False
     text_type = unicode
@@ -49,10 +51,10 @@
 
     def u(s):
         return s
-
 # }}}
 # _pofile_or_mofile {{{
 
+
 def _pofile_or_mofile(f, type, **kwargs):
     """
     Internal function used by :func:`polib.pofile` and :func:`polib.mofile` to
@@ -69,15 +71,15 @@
         f,
         encoding=enc,
         check_for_duplicates=kwargs.get('check_for_duplicates', False),
-        klass = kwargs.get('klass')
+        klass=kwargs.get('klass')
     )
     instance = parser.parse()
     instance.wrapwidth = kwargs.get('wrapwidth', 78)
     return instance
-
 # }}}
 # function pofile() {{{
 
+
 def pofile(pofile, **kwargs):
     """
     Convenience function that parses the po or pot file ``pofile`` and returns
@@ -99,17 +101,17 @@
     ``check_for_duplicates``
         whether to check for duplicate entries when adding entries to the
         file (optional, default: ``False``).
-        
+
     ``klass``
         class which is used to instantiate the return value (optional,
         default: ``None``, the return value with be a :class:`~polib.POFile`
         instance).
     """
     return _pofile_or_mofile(pofile, 'pofile', **kwargs)
-
 # }}}
 # function mofile() {{{
 
+
 def mofile(mofile, **kwargs):
     """
     Convenience function that parses the mo file ``mofile`` and returns a
@@ -132,17 +134,17 @@
     ``check_for_duplicates``
         whether to check for duplicate entries when adding entries to the
         file (optional, default: ``False``).
-        
+
     ``klass``
         class which is used to instantiate the return value (optional,
         default: ``None``, the return value with be a :class:`~polib.POFile`
         instance).
     """
     return _pofile_or_mofile(mofile, 'mofile', **kwargs)
-
 # }}}
 # function detect_encoding() {{{
 
+
 def detect_encoding(file, binary_mode=False):
     """
     Try to detect the encoding used by the ``file``. The ``file`` argument can
@@ -170,7 +172,12 @@
             return False
         return True
 
-    if not os.path.exists(file):
+    try:
+        is_file = os.path.exists(file)
+    except (ValueError, UnicodeEncodeError):
+        is_file = False
+
+    if not is_file:
         match = rxt.search(file)
         if match:
             enc = match.group(1).strip()
@@ -196,10 +203,10 @@
                     return enc
         f.close()
     return default_encoding
-
 # }}}
 # function escape() {{{
 
+
 def escape(st):
     """
     Escapes the characters ``\\\\``, ``\\t``, ``\\n``, ``\\r`` and ``"`` in
@@ -210,10 +217,10 @@
              .replace('\r', r'\r')\
              .replace('\n', r'\n')\
              .replace('\"', r'\"')
-
 # }}}
 # function unescape() {{{
 
+
 def unescape(st):
     """
     Unescapes the characters ``\\\\``, ``\\t``, ``\\n``, ``\\r`` and ``"`` in
@@ -229,12 +236,12 @@
             return '\r'
         if m == '\\':
             return '\\'
-        return m # handles escaped double quote
+        return m  # handles escaped double quote
     return re.sub(r'\\(\\|n|t|r|")', unescape_repl, st)
-
 # }}}
 # class _BaseFile {{{
 
+
 class _BaseFile(list):
     """
     Common base class for the :class:`~polib.POFile` and :class:`~polib.MOFile`
@@ -312,15 +319,17 @@
         Overriden ``list`` method to implement the membership test (in and
         not in).
         The method considers that an entry is in the file if it finds an entry
-        that has the same msgid (the test is **case sensitive**).
+        that has the same msgid (the test is **case sensitive**) and the same
+        msgctxt (or none for both entries).
 
         Argument:
 
         ``entry``
             an instance of :class:`~polib._BaseEntry`.
         """
-        return self.find(entry.msgid, by='msgid') is not None
-    
+        return self.find(entry.msgid, by='msgid', msgctxt=entry.msgctxt) \
+            is not None
+
     def __eq__(self, other):
         return str(self) == str(other)
 
@@ -431,7 +440,7 @@
             entries = [e for e in self if not e.obsolete]
         for e in entries:
             if getattr(e, by) == st:
-                if msgctxt and e.msgctxt != msgctxt:
+                if msgctxt is not False and e.msgctxt != msgctxt:
                     continue
                 return e
         return None
@@ -439,7 +448,7 @@
     def ordered_metadata(self):
         """
         Convenience method that returns an ordered version of the metadata
-        dictionnary. The return value is list of tuples (metadata name,
+        dictionary. The return value is list of tuples (metadata name,
         metadata_value).
         """
         # copy the dict first
@@ -475,6 +484,7 @@
         """
         offsets = []
         entries = self.translated_entries()
+
         # the keys are sorted in the .mo file
         def cmp(_self, other):
             # msgfmt compares entries with msgctxt if it exists
@@ -511,11 +521,11 @@
                 msgid += self._encode(e.msgid)
                 msgstr = self._encode(e.msgstr)
             offsets.append((len(ids), len(msgid), len(strs), len(msgstr)))
-            ids  += msgid  + b('\0')
+            ids += msgid + b('\0')
             strs += msgstr + b('\0')
 
         # The header is 7 32-bit unsigned integers.
-        keystart = 7*4+16*entries_len
+        keystart = 7 * 4 + 16 * entries_len
         # and the values start after the keys
         valuestart = keystart + len(ids)
         koffsets = []
@@ -523,8 +533,8 @@
         # The string table first has the list of keys, then the list of values.
         # Each entry has first the size of the string, then the file offset.
         for o1, l1, o2, l2 in offsets:
-            koffsets += [l1, o1+keystart]
-            voffsets += [l2, o2+valuestart]
+            koffsets += [l1, o1 + keystart]
+            voffsets += [l2, o2 + valuestart]
         offsets = koffsets + voffsets
         # check endianness for magic number
         if struct.pack('@h', 1) == struct.pack('<h', 1):
@@ -534,13 +544,19 @@
 
         output = struct.pack(
             "Iiiiiii",
-            magic_number,      # Magic number
-            0,                 # Version
-            entries_len,       # # of entries
-            7*4,               # start of key index
-            7*4+entries_len*8, # start of value index
-            0, keystart        # size and offset of hash table
-                               # Important: we don't use hash tables
+            # Magic number
+            magic_number,
+            # Version
+            0,
+            # number of entries
+            entries_len,
+            # start of key index
+            7 * 4,
+            # start of value index
+            7 * 4 + entries_len * 8,
+            # size and offset of hash table, we don't use hash tables
+            0, keystart
+
         )
         if PY3 and sys.version_info.minor > 1:  # python 3.2 or superior
             output += array.array("i", offsets).tobytes()
@@ -558,10 +574,10 @@
         if isinstance(mixed, text_type):
             mixed = mixed.encode(self.encoding)
         return mixed
-
 # }}}
 # class POFile {{{
 
+
 class POFile(_BaseFile):
     """
     Po (or Pot) file reader/writer.
@@ -617,7 +633,7 @@
         """
         Convenience method that returns the list of untranslated entries.
         """
-        return [e for e in self if not e.translated() and not e.obsolete \
+        return [e for e in self if not e.translated() and not e.obsolete
                 and not 'fuzzy' in e.flags]
 
     def fuzzy_entries(self):
@@ -662,22 +678,22 @@
         for entry in self:
             if entry.msgid not in refpot_msgids:
                 entry.obsolete = True
-
 # }}}
 # class MOFile {{{
 
+
 class MOFile(_BaseFile):
     """
     Mo file reader/writer.
     This class inherits the :class:`~polib._BaseFile` class and, by
     extension, the python ``list`` type.
     """
-    BIG_ENDIAN    = 0xde120495
+    BIG_ENDIAN = 0xde120495
     LITTLE_ENDIAN = 0x950412de
 
     def __init__(self, *args, **kwargs):
         """
-        Constructor, accepts all keywords arguments accepted by 
+        Constructor, accepts all keywords arguments accepted by
         :class:`~polib._BaseFile` class.
         """
         _BaseFile.__init__(self, *args, **kwargs)
@@ -735,10 +751,10 @@
         Convenience method to keep the same interface with POFile instances.
         """
         return []
-
 # }}}
 # class _BaseEntry {{{
 
+
 class _BaseEntry(object):
     """
     Base class for :class:`~polib.POEntry` and :class:`~polib.MOEntry` classes.
@@ -790,12 +806,14 @@
         ret = []
         # write the msgctxt if any
         if self.msgctxt is not None:
-            ret += self._str_field("msgctxt", delflag, "", self.msgctxt, 
wrapwidth)
+            ret += self._str_field("msgctxt", delflag, "", self.msgctxt,
+                                   wrapwidth)
         # write the msgid
         ret += self._str_field("msgid", delflag, "", self.msgid, wrapwidth)
         # write the msgid_plural if any
         if self.msgid_plural:
-            ret += self._str_field("msgid_plural", delflag, "", 
self.msgid_plural, wrapwidth)
+            ret += self._str_field("msgid_plural", delflag, "",
+                                   self.msgid_plural, wrapwidth)
         if self.msgstr_plural:
             # write the msgstr_plural if any
             msgstrs = self.msgstr_plural
@@ -804,10 +822,12 @@
             for index in keys:
                 msgstr = msgstrs[index]
                 plural_index = '[%s]' % index
-                ret += self._str_field("msgstr", delflag, plural_index, 
msgstr, wrapwidth)
+                ret += self._str_field("msgstr", delflag, plural_index, msgstr,
+                                       wrapwidth)
         else:
             # otherwise write the msgstr
-            ret += self._str_field("msgstr", delflag, "", self.msgstr, 
wrapwidth)
+            ret += self._str_field("msgstr", delflag, "", self.msgstr,
+                                   wrapwidth)
         ret.append('')
         ret = u('\n').join(ret)
         return ret
@@ -821,20 +841,21 @@
             Returns the string representation of the entry.
             """
             return unicode(self).encode(self.encoding)
-    
+
     def __eq__(self, other):
         return str(self) == str(other)
 
-    def _str_field(self, fieldname, delflag, plural_index, field, 
wrapwidth=78):
+    def _str_field(self, fieldname, delflag, plural_index, field,
+                   wrapwidth=78):
         lines = field.splitlines(True)
         if len(lines) > 1:
-            lines = [''] + lines # start with initial empty line
+            lines = [''] + lines  # start with initial empty line
         else:
             escaped_field = escape(field)
             specialchars_count = 0
             for c in ['\\', '\n', '\r', '\t', '"']:
                 specialchars_count += field.count(c)
-            # comparison must take into account fieldname length + one space 
+            # comparison must take into account fieldname length + one space
             # + 2 quotes (eg. msgid "<string>")
             flength = len(fieldname) + 3
             if plural_index:
@@ -844,7 +865,7 @@
                 # Wrap the line but take field name into account
                 lines = [''] + [unescape(item) for item in wrap(
                     escaped_field,
-                    wrapwidth - 2, # 2 for quotes ""
+                    wrapwidth - 2,  # 2 for quotes ""
                     drop_whitespace=False,
                     break_long_words=False
                 )]
@@ -860,10 +881,10 @@
             #import pdb; pdb.set_trace()
             ret.append('%s"%s"' % (delflag, escape(mstr)))
         return ret
-
 # }}}
 # class POEntry {{{
 
+
 class POEntry(_BaseEntry):
     """
     Represents a po file entry.
@@ -938,9 +959,9 @@
                     filelist.append(fpath)
             filestr = ' '.join(filelist)
             if wrapwidth > 0 and len(filestr) + 3 > wrapwidth:
-                # textwrap split words that contain hyphen, this is not 
-                # what we want for filenames, so the dirty hack is to 
-                # temporally replace hyphens with a char that a file cannot 
+                # textwrap split words that contain hyphen, this is not
+                # what we want for filenames, so the dirty hack is to
+                # temporally replace hyphens with a char that a file cannot
                 # contain, like "*"
                 ret += [l.replace('*', '-') for l in wrap(
                     filestr.replace('-', '*'),
@@ -957,7 +978,8 @@
             ret.append('#, %s' % ', '.join(self.flags))
 
         # previous context and previous msgid/msgid_plural
-        fields = ['previous_msgctxt', 'previous_msgid', 
'previous_msgid_plural']
+        fields = ['previous_msgctxt', 'previous_msgid',
+                  'previous_msgid_plural']
         for f in fields:
             val = getattr(self, f)
             if val:
@@ -1003,8 +1025,10 @@
                 else:
                     return -1
         # Finally: Compare message ID
-        if self.msgid > other.msgid: return 1
-        elif self.msgid < other.msgid: return -1
+        if self.msgid > other.msgid:
+            return 1
+        elif self.msgid < other.msgid:
+            return -1
         return 0
 
     def __gt__(self, other):
@@ -1065,19 +1089,19 @@
                     self.msgstr_plural[pos]
                 except KeyError:
                     self.msgstr_plural[pos] = ''
-
 # }}}
 # class MOEntry {{{
 
+
 class MOEntry(_BaseEntry):
     """
     Represents a mo file entry.
     """
     pass
-
 # }}}
 # class _POFileParser {{{
 
+
 class _POFileParser(object):
     """
     A finite state machine to parse efficiently and correctly po
@@ -1157,7 +1181,7 @@
         self.add('PP', all,                                              'PP')
         self.add('CT', ['ST', 'HE', 'GC', 'OC', 'FL', 'TC', 'PC', 'PM',
                         'PP', 'MS', 'MX'],                               'CT')
-        self.add('MI', ['ST', 'HE', 'GC', 'OC', 'FL', 'CT', 'TC', 'PC', 
+        self.add('MI', ['ST', 'HE', 'GC', 'OC', 'FL', 'CT', 'TC', 'PC',
                  'PM', 'PP', 'MS', 'MX'],                                'MI')
         self.add('MP', ['TC', 'GC', 'PC', 'PM', 'PP', 'MI'],             'MP')
         self.add('MS', ['MI', 'MP', 'TC'],                               'MS')
@@ -1208,8 +1232,8 @@
             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' % \
+                    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)
@@ -1217,15 +1241,17 @@
 
             self.current_token = line
 
-            if tokens[0] == '#:' and nb_tokens > 1:
+            if tokens[0] == '#:':
+                if nb_tokens <= 1:
+                    continue
                 # 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' % \
+                    raise IOError('Syntax error in po file %s (line %s): '
+                                  'unescaped double quote found' %
                                   (self.instance.fpath, i))
                 self.process('MC', i)
 
@@ -1233,22 +1259,27 @@
                 # we are on a msgstr plural
                 self.process('MX', i)
 
-            elif tokens[0] == '#,' and nb_tokens >= 1:
+            elif tokens[0] == '#,':
+                if nb_tokens <= 1:
+                    continue
                 # we are on a flags line
                 self.process('FL', i)
 
             elif tokens[0] == '#' or tokens[0].startswith('##'):
-                if line == '#': line += ' '
+                if line == '#':
+                    line += ' '
                 # we are on a translator comment line
                 self.process('TC', i)
 
-            elif tokens[0] == '#.' and nb_tokens >= 1:
+            elif tokens[0] == '#.':
+                if nb_tokens <= 1:
+                    continue
                 # we are on a generated comment line
                 self.process('GC', i)
 
             elif tokens[0] == '#|':
-                if nb_tokens < 2:
-                    raise IOError('Syntax error in po file %s (line %s)' % \
+                if nb_tokens <= 1:
+                    raise IOError('Syntax error in po file %s (line %s)' %
                                   (self.instance.fpath, i))
 
                 # Remove the marker and any whitespace right after that.
@@ -1262,15 +1293,15 @@
 
                 if nb_tokens == 2:
                     # Invalid continuation line.
-                    raise IOError('Syntax error in po file %s (line %s): '\
-                                  'invalid continuation line' % \
+                    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.
-                    raise IOError('Syntax error in po file %s (line %s): '\
-                                  'unknown keyword %s' % \
+                    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
@@ -1280,17 +1311,17 @@
                 self.process(prev_keywords[tokens[1]], i)
 
             else:
-                raise IOError('Syntax error in po file %s (line %s)' % \
+                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 
+        # before returning the instance, check if there's metadata and if
         # so extract it in a dict
         metadataentry = self.instance.find('')
-        if metadataentry: # metadata found
+        if metadataentry:  # metadata found
             # remove the entry
             self.instance.remove(metadataentry)
             self.instance.metadata_is_fuzzy = metadataentry.flags
@@ -1299,9 +1330,9 @@
                 try:
                     key, val = msg.split(':', 1)
                     self.instance.metadata[key] = val.strip()
-                except:
+                except (ValueError, KeyError):
                     if key is not None:
-                        self.instance.metadata[key] += '\n'+ msg.strip()
+                        self.instance.metadata[key] += '\n' + msg.strip()
         # close opened file
         if not isinstance(self.fhandle, list):  # must be file
             self.fhandle.close()
@@ -1389,10 +1420,10 @@
                 try:
                     fil, line = occurrence.split(':')
                     if not line.isdigit():
-                        fil  = fil + line
+                        fil = fil + line
                         line = ''
                     self.current_entry.occurrences.append((fil, line))
-                except:
+                except (ValueError, AttributeError):
                     self.current_entry.occurrences.append((occurrence, ''))
         return True
 
@@ -1469,38 +1500,30 @@
         """Handle a msgid or msgstr continuation line."""
         token = unescape(self.current_token[1:-1])
         if self.current_state == 'CT':
-            typ = 'msgctxt'
             self.current_entry.msgctxt += token
         elif self.current_state == 'MI':
-            typ = 'msgid'
             self.current_entry.msgid += token
         elif self.current_state == 'MP':
-            typ = 'msgid_plural'
             self.current_entry.msgid_plural += token
         elif self.current_state == 'MS':
-            typ = 'msgstr'
             self.current_entry.msgstr += token
         elif self.current_state == 'MX':
-            typ = 'msgstr[%s]' % self.msgstr_index
             self.current_entry.msgstr_plural[self.msgstr_index] += token
         elif self.current_state == 'PP':
-            typ = 'previous_msgid_plural'
             token = token[3:]
             self.current_entry.previous_msgid_plural += token
         elif self.current_state == 'PM':
-            typ = 'previous_msgid'
             token = token[3:]
             self.current_entry.previous_msgid += token
         elif self.current_state == 'PC':
-            typ = 'previous_msgctxt'
             token = token[3:]
             self.current_entry.previous_msgctxt += token
         # don't change the current state
         return False
-
 # }}}
 # class _MOFileParser {{{
 
+
 class _MOFileParser(object):
     """
     A class to parse binary mo files.
@@ -1570,7 +1593,7 @@
 
             self.fhandle.seek(msgstrs_index[i][1])
             msgstr = self.fhandle.read(msgstrs_index[i][0])
-            if i == 0: # metadata
+            if i == 0:  # metadata
                 raw_metadata, metadata = msgstr.split(b('\n')), {}
                 for line in raw_metadata:
                     tokens = line.split(b(':'), 1)
@@ -1589,7 +1612,8 @@
                 entry = self._build_entry(
                     msgid=msgid_tokens[0],
                     msgid_plural=msgid_tokens[1],
-                    msgstr_plural=dict((k,v) for k,v in 
enumerate(msgstr.split(b('\0'))))
+                    msgstr_plural=dict((k, v) for k, v in
+                                       enumerate(msgstr.split(b('\0'))))
                 )
             else:
                 entry = self._build_entry(msgid=msgid, msgstr=msgstr)
@@ -1605,7 +1629,7 @@
         if len(msgctxt_msgid) > 1:
             kwargs = {
                 'msgctxt': msgctxt_msgid[0].decode(encoding),
-                'msgid'  : msgctxt_msgid[1].decode(encoding),
+                'msgid': msgctxt_msgid[1].decode(encoding),
             }
         else:
             kwargs = {'msgid': msgid.decode(encoding)}
@@ -1629,17 +1653,17 @@
         if len(tup) == 1:
             return tup[0]
         return tup
-
 # }}}
 # class TextWrapper {{{
 
+
 class TextWrapper(textwrap.TextWrapper):
     """
     Subclass of textwrap.TextWrapper that backport the
     drop_whitespace option.
     """
     def __init__(self, *args, **kwargs):
-        drop_whitespace = kwargs.pop('drop_whitespace', True) 
+        drop_whitespace = kwargs.pop('drop_whitespace', True)
         textwrap.TextWrapper.__init__(self, *args, **kwargs)
         self.drop_whitespace = drop_whitespace
 
@@ -1703,7 +1727,7 @@
                 self._handle_long_word(chunks, cur_line, cur_len, width)
 
             # If the last chunk on this line is all whitespace, drop it.
-            if self.drop_whitespace and cur_line and cur_line[-1].strip() == 
'':
+            if self.drop_whitespace and cur_line and not cur_line[-1].strip():
                 del cur_line[-1]
 
             # Convert current line back to a string and store it in list
@@ -1712,10 +1736,10 @@
                 lines.append(indent + ''.join(cur_line))
 
         return lines
-
 # }}}
 # function wrap() {{{
 
+
 def wrap(text, width=70, **kwargs):
     """
     Wrap a single paragraph of text, returning a list of wrapped lines.
@@ -1724,4 +1748,4 @@
         return TextWrapper(width=width, **kwargs).wrap(text)
     return textwrap.wrap(text, width=width, **kwargs)
 
-#}}}
+# }}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/setup.py new/polib-1.0.3/setup.py
--- old/polib-1.0.1/setup.py    2012-06-08 21:48:16.000000000 +0200
+++ new/polib-1.0.3/setup.py    2013-02-09 18:33:22.000000000 +0100
@@ -11,20 +11,28 @@
 __author__ = 'David Jean Louis <[email protected]>'
 
 from distutils.core import setup
+import codecs
+
 import polib
 
 author_data = __author__.split(' ')
 maintainer = ' '.join(author_data[0:-1])
 maintainer_email = author_data[-1]
 desc = 'A library to manipulate gettext files (po and mo files).'
-long_desc = '''
+
+if polib.PY3:
+    mode = 'rb'
+else:
+    mode = 'r'
+
+long_desc = r'''
 .. contents:: Table of Contents
 
 %s
 
 %s
 
-''' % (open('README.rst').read(), open('CHANGELOG').read())
+''' % (open('README.rst', mode).read(), open('CHANGELOG', mode).read())
 
 if __name__ == '__main__':
     setup(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/tests/test_pofile_helpers.po 
new/polib-1.0.3/tests/test_pofile_helpers.po
--- old/polib-1.0.1/tests/test_pofile_helpers.po        2011-08-01 
18:45:10.000000000 +0200
+++ new/polib-1.0.3/tests/test_pofile_helpers.po        2012-12-06 
11:11:00.000000000 +0100
@@ -26,6 +26,13 @@
 msgid "and"
 msgstr "y"
 
+#: db/models/manipulators.py:310 contrib/admin/views/main.py:342
+#: contrib/admin/views/main.py:344 contrib/admin/views/main.py:346
+#: core/validators.py:275
+msgctxt "some context"
+msgid "and"
+msgstr "y"
+
 #: db/models/fields/__init__.py:49
 #, python-format
 msgid "%(optname)s with this %(fieldname)s already exists."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/tests/test_utf8.po 
new/polib-1.0.3/tests/test_utf8.po
--- old/polib-1.0.1/tests/test_utf8.po  2012-09-11 10:13:42.000000000 +0200
+++ new/polib-1.0.3/tests/test_utf8.po  2012-10-23 12:33:30.000000000 +0200
@@ -38,6 +38,12 @@
 msgid "Some msgid"
 msgstr "Some msgstr"
 
+#. test generated comments
+#.
+#. more tests...
+msgid "Test generated comments"
+msgstr "Test generated comments"
+
 # Added for previous msgid/msgid_plural/msgctxt testing
 #| msgctxt "@previous_context"
 #| msgid ""
@@ -60,12 +66,14 @@
 ## Some comment starting with two '#'
 #: db/models/manipulators.py:309
 #, python-format
+#,
 msgid "%(object)s with this %(type)s already exists for the given %(field)s."
 msgstr "%(object)s de este %(type)s ya existen en este %(field)s."
 
 #: db/models/manipulators.py:310 contrib/admin/views/main.py:342
 #: contrib/admin/views/main.py:344 contrib/admin/views/main.py:346
 #: core/validators.py:275
+#:
 msgid "and"
 msgstr "y"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/polib-1.0.1/tests/tests.py 
new/polib-1.0.3/tests/tests.py
--- old/polib-1.0.1/tests/tests.py      2012-09-11 10:13:12.000000000 +0200
+++ new/polib-1.0.3/tests/tests.py      2013-02-09 18:21:20.000000000 +0100
@@ -185,9 +185,14 @@
         """
         Test with utf8 data (no file).
         """
-        f = open('tests/test_utf8.po','r')
+        if polib.PY3:
+            f = open('tests/test_utf8.po', 'rb')
+            data = str(f.read(), 'utf-8')
+        else:
+            f = open('tests/test_utf8.po', 'r')
+            data = f.read()
         try:
-            self.assertEqual(polib.detect_encoding(f.read()), 'UTF-8')
+            self.assertEqual(polib.detect_encoding(data), 'UTF-8')
         finally:
             f.close()    
 
@@ -264,9 +269,21 @@
     def test_append2(self):
         def add_duplicate():
             pofile = polib.pofile('tests/test_pofile_helpers.po', 
check_for_duplicates=True)
-            pofile.append(polib.POEntry(msgid="and", msgstr="y"))
+            pofile.append(polib.POEntry(msgid="and"))
+        self.assertRaises(ValueError, add_duplicate)
+
+    def test_append3(self):
+        def add_duplicate():
+            pofile = polib.pofile('tests/test_pofile_helpers.po', 
check_for_duplicates=True)
+            pofile.append(polib.POEntry(msgid="and", msgctxt="some context"))
         self.assertRaises(ValueError, add_duplicate)
 
+    def test_append4(self):
+        pofile = polib.pofile('tests/test_pofile_helpers.po', 
check_for_duplicates=True)
+        entry = polib.POEntry(msgid="and", msgctxt="some different context")
+        pofile.append(entry)
+        self.assertTrue(entry in pofile)
+
     def test_insert1(self):
         pofile = polib.pofile('tests/test_pofile_helpers.po')
         entry = polib.POEntry(msgid="Foo", msgstr="Bar", msgctxt="Some 
context")
@@ -445,6 +462,13 @@
         """
         Test for the POFile.save_as_mofile() method.
         """
+        import distutils.spawn
+        msgfmt = distutils.spawn.find_executable('msgfmt')
+        if msgfmt is None:
+            try:
+                return unittest.skip('msgfmt is not installed')
+            except AttributeError:
+                return
         reffiles = ['tests/test_utf8.po', 'tests/test_iso-8859-15.po']
         encodings = ['utf-8', 'iso-8859-15']
         for reffile, encoding in zip(reffiles, encodings):
@@ -454,7 +478,7 @@
             os.close(fd)
             po = polib.pofile(reffile, autodetect_encoding=False, 
encoding=encoding)
             po.save_as_mofile(tmpfile1)
-            subprocess.call(['msgfmt', '--no-hash', '-o', tmpfile2, reffile])
+            subprocess.call([msgfmt, '--no-hash', '-o', tmpfile2, reffile])
             try:
                 f = open(tmpfile1, 'rb')
                 s1 = f.read()
@@ -476,13 +500,13 @@
 
     def test_percent_translated(self):
         po = polib.pofile('tests/test_pofile_helpers.po')
-        self.assertEqual(po.percent_translated(), 50)
+        self.assertEqual(po.percent_translated(), 53)
         po = polib.POFile()
         self.assertEqual(po.percent_translated(), 100)
 
     def test_translated_entries(self):
         po = polib.pofile('tests/test_pofile_helpers.po')
-        self.assertEqual(len(po.translated_entries()), 6)
+        self.assertEqual(len(po.translated_entries()), 7)
 
     def test_untranslated_entries(self):
         po = polib.pofile('tests/test_pofile_helpers.po')
@@ -530,10 +554,16 @@
         mo = polib.mofile('tests/test_utf8.mo', wrapwidth=78)
         mo.save_as_pofile(tmpfile)
         try:
-            f = open(tmpfile)
+            if polib.PY3:
+                f = open(tmpfile, encoding='utf-8')
+            else:
+                f = open(tmpfile)
             s1 = f.read()
             f.close()
-            f = open('tests/test_save_as_pofile.po')
+            if polib.PY3:
+                f = open('tests/test_save_as_pofile.po', encoding='utf-8')
+            else:
+                f = open('tests/test_save_as_pofile.po')
             s2 = f.read()
             f.close()
             self.assertEqual(s1, s2)

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to