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 - p.drouand@gmail.com
+
+- 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:
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 '
-__version__ = '1.0.1'
-__all__ = ['pofile', 'POFile', 'POEntry', 'mofile', 'MOFile', 'MOEntry',
- 'detect_encoding', 'escape', 'unescape', 'detect_encoding',]
+__author__ = 'David Jean Louis '
+__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(' 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 '
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: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org