from babel._compat import text_type
+
def unescape(string):
r"""Reverse `escape` the given string.
return unescape(string)
+class PoFileError(Exception):
+ """Exception thrown by PoParser when an invalid po file is encountered."""
+ def __init__(self, message, catalog, line, lineno):
+ super(PoFileError, self).__init__('{message} on {lineno}'.format(message=message, lineno=lineno))
+ self.catalog = catalog
+ self.line = line
+ self.lineno = lineno
+
+
class _NormalizedString(object):
def __init__(self, *args):
'msgid_plural',
]
- def __init__(self, catalog, ignore_obsolete=False):
+ def __init__(self, catalog, ignore_obsolete=False, abort_invalid=False):
self.catalog = catalog
self.ignore_obsolete = ignore_obsolete
self.counter = 0
self.offset = 0
+ self.abort_invalid = abort_invalid
self._reset_message_state()
def _reset_message_state(self):
self._add_message()
def _invalid_pofile(self, line, lineno, msg):
+ if self.abort_invalid:
+ raise PoFileError(msg, self.catalog, line, lineno)
print("WARNING:", msg)
print("WARNING: Problem on line {0}: {1}".format(lineno + 1, line))
-def read_po(fileobj, locale=None, domain=None, ignore_obsolete=False, charset=None):
+def read_po(fileobj, locale=None, domain=None, ignore_obsolete=False, charset=None, abort_invalid=False):
"""Read messages from a ``gettext`` PO (portable object) file from the given
file-like object and return a `Catalog`.
:param domain: the message domain
:param ignore_obsolete: whether to ignore obsolete messages in the input
:param charset: the character set of the catalog.
+ :param abort_invalid: abort read if po file is invalid
"""
catalog = Catalog(locale=locale, domain=domain, charset=charset)
- parser = PoFileParser(catalog, ignore_obsolete)
+ parser = PoFileParser(catalog, ignore_obsolete, abort_invalid=abort_invalid)
parser.parse(fileobj)
return catalog
from datetime import datetime
import unittest
+import sys
from babel.core import Locale
from babel.messages.catalog import Catalog, Message
from babel.util import FixedOffsetTimezone
from babel._compat import StringIO, BytesIO
-
class ReadPoTestCase(unittest.TestCase):
def test_preserve_locale(self):
self.assertEqual("", message.string[1])
self.assertEqual("Vohs [text]", message.string[2])
+ def test_abort_invalid_po_file(self):
+ invalid_po = '''
+ msgctxt ""
+ "{\"checksum\": 2148532640, \"cxt\": \"collector_thankyou\", \"id\": "
+ "270005359}"
+ msgid ""
+ "Thank you very much for your time.\n"
+ "If you have any questions regarding this survey, please contact Fulano "
+ "at nadie@blah.com"
+ msgstr "Merci de prendre le temps de remplir le sondage.
+ Pour toute question, veuillez communiquer avec Fulano à nadie@blah.com
+ "
+ '''
+ invalid_po_2 = '''
+ msgctxt ""
+ "{\"checksum\": 2148532640, \"cxt\": \"collector_thankyou\", \"id\": "
+ "270005359}"
+ msgid ""
+ "Thank you very much for your time.\n"
+ "If you have any questions regarding this survey, please contact Fulano "
+ "at fulano@blah.com."
+ msgstr "Merci de prendre le temps de remplir le sondage.
+ Pour toute question, veuillez communiquer avec Fulano a fulano@blah.com
+ "
+ '''
+ # Catalog not created, throws Unicode Error
+ buf = StringIO(invalid_po)
+ output = None
+
+ # This should only be thrown under py27
+ if sys.version_info.major == 2:
+ with self.assertRaises(UnicodeEncodeError):
+ output = pofile.read_po(buf, locale='fr', abort_invalid=False)
+ assert not output
+ else:
+ output = pofile.read_po(buf, locale='fr', abort_invalid=False)
+ assert isinstance(output, Catalog)
+
+ # Catalog not created, throws PoFileError
+ buf = StringIO(invalid_po_2)
+ output = None
+ with self.assertRaises(pofile.PoFileError) as e:
+ output = pofile.read_po(buf, locale='fr', abort_invalid=True)
+ assert not output
+
+ # Catalog is created with warning, no abort
+ buf = StringIO(invalid_po_2)
+ output = pofile.read_po(buf, locale='fr', abort_invalid=False)
+ assert isinstance(output, Catalog)
+
+ # Catalog not created, aborted with PoFileError
+ buf = StringIO(invalid_po_2)
+ output = None
+ with self.assertRaises(pofile.PoFileError) as e:
+ output = pofile.read_po(buf, locale='fr', abort_invalid=True)
+ assert not output
+
+ def test_invalid_pofile_with_abort_flag(self):
+ parser = pofile.PoFileParser(None, abort_invalid=True)
+ lineno = 10
+ line = 'Algo esta mal'
+ msg = 'invalid file'
+ with self.assertRaises(pofile.PoFileError) as e:
+ parser._invalid_pofile(line, lineno, msg)
class WritePoTestCase(unittest.TestCase):