# HG changeset patch # User palgarvio # Date 1182876416 0 # Node ID 3c4718fb7435b078e7eb739d7b1f633b109c4429 # Parent 456ee094198742b74de33c9c30b59b558648759a Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing). The `Catalog` class now also includes an extra attribute, '''`fuzzy`''', which is the fuzzy bit of the catalog header. The above change allows the `compile_catalog` frontends to only compile catalogs '''not''' marked as fuzzy, unless `--use-fuzzy` is passed. Added tests to check header fuzzy bit parsing. diff --git a/babel/messages/catalog.py b/babel/messages/catalog.py --- a/babel/messages/catalog.py +++ b/babel/messages/catalog.py @@ -66,7 +66,8 @@ self.user_comments = list(user_comments) def __repr__(self): - return '<%s %r>' % (type(self).__name__, self.id) + return '<%s %r (Flags: %r)>' % (type(self).__name__, self.id, + ', '.join([flag for flag in self.flags])) def fuzzy(self): return 'fuzzy' in self.flags @@ -75,8 +76,11 @@ >>> Message('foo').fuzzy False - >>> Message('foo', 'foo', flags=['fuzzy']).fuzzy + >>> msg = Message('foo', 'foo', flags=['fuzzy']) + >>> msg.fuzzy True + >>> msg + :type: `bool` """) @@ -124,7 +128,8 @@ def __init__(self, locale=None, domain=None, header_comment=DEFAULT_HEADER, project=None, version=None, copyright_holder=None, msgid_bugs_address=None, creation_date=None, - revision_date=None, last_translator=None, charset='utf-8'): + revision_date=None, last_translator=None, charset='utf-8', + fuzzy=True): """Initialize the catalog object. :param locale: the locale identifier or `Locale` object, or `None` @@ -142,6 +147,7 @@ :param revision_date: the date the catalog was revised :param last_translator: the name and email of the last translator :param charset: the encoding to use in the output + :param fuzzy: the fuzzy bit on the catalog header """ self.domain = domain #: The message domain if locale: @@ -170,6 +176,7 @@ elif isinstance(revision_date, datetime) and not revision_date.tzinfo: revision_date = revision_date.replace(tzinfo=LOCALTZ) self.revision_date = revision_date #: Last revision date of the catalog + self.fuzzy = fuzzy #: Catalog Header fuzzy bit(True or False) def _get_header_comment(self): comment = self._header_comment @@ -376,7 +383,11 @@ buf = [] for name, value in self.mime_headers: buf.append('%s: %s' % (name, value)) - yield Message('', '\n'.join(buf), flags=set(['fuzzy'])) + if self.fuzzy: + flags = set(['fuzzy']) + else: + flags = set() + yield Message('', '\n'.join(buf), flags=flags) for key in self._messages: yield self._messages[key] @@ -408,7 +419,7 @@ >>> catalog = Catalog() >>> catalog[u'foo'] = Message(u'foo') >>> catalog[u'foo'] - + If a message with that ID is already in the catalog, it is updated to include the locations and flags of the new message. @@ -455,7 +466,7 @@ >>> catalog = Catalog() >>> catalog.add(u'foo') >>> catalog[u'foo'] - + This method simply constructs a `Message` object with the given arguments and invokes `__setitem__` with that object. @@ -504,7 +515,7 @@ >>> 'head' in catalog False >>> rest - [] + [] :param template: the reference catalog, usually read from a POT file :param fuzzy_matching: whether to use fuzzy matching of message IDs diff --git a/babel/messages/frontend.py b/babel/messages/frontend.py --- a/babel/messages/frontend.py +++ b/babel/messages/frontend.py @@ -99,7 +99,7 @@ po_path = os.path.join(self.directory, locale, 'LC_MESSAGES', self.domain + '.po') if os.path.exists(po_path): - self._available_pos.append(po_path) + self._available_pos.append((locale, po_path)) else: raise DistutilsOptionError('you must specify the locale for the' ' catalog to compile') @@ -111,7 +111,7 @@ if not self.directory and not self.input_file: raise DistutilsOptionError('you must specify the input file') - if not self.input_file: + if not self.input_file and not self.compile_all: self.input_file = os.path.join(self.directory, self.locale, 'LC_MESSAGES', self.domain + '.po') @@ -127,29 +127,38 @@ def run(self): if self.compile_all: - for po in self._available_pos: - log.info('compiling catalog to %s', po.replace('.po', '.mo')) - + for locale, po in self._available_pos: + loc_name = Locale.parse(locale).english_name infile = open(po, 'r') try: catalog = read_po(infile) finally: infile.close() - + if catalog.fuzzy and not self.use_fuzzy: + log.error('%s catalog %r is marked as fuzzy, not compiling' + ' it', loc_name, po) + continue + + log.info('compiling %s catalog to %s', + loc_name, + po.replace('.po', '.mo')) + outfile = open(po.replace('.po', '.mo'), 'w') try: write_mo(outfile, catalog, use_fuzzy=self.use_fuzzy) finally: outfile.close() else: - log.info('compiling catalog to %s', self.output_file) - infile = open(self.input_file, 'r') try: catalog = read_po(infile) finally: infile.close() - + if catalog.fuzzy: + log.error('catalog is marked as fuzzy, not compiling it') + sys.exit(0) + + log.info('compiling catalog to %s', self.output_file) outfile = open(self.output_file, 'w') try: write_mo(outfile, catalog, use_fuzzy=self.use_fuzzy) @@ -519,7 +528,7 @@ 'LC_MESSAGES', options.domain + '.po') if os.path.exists(po_path): - available_pos.append(po_path) + available_pos.append((locale, po_path)) else: parser.error('you must provide a locale for the new catalog') else: @@ -530,7 +539,7 @@ if not options.directory and not options.input_file: parser.error('you must specify the base directory or input file') - if not options.input_file: + if not options.input_file and not options.compile_all: options.input_file = os.path.join(options.directory, options.locale, 'LC_MESSAGES', options.domain + '.po') @@ -551,6 +560,10 @@ catalog = read_po(infile) finally: infile.close() + + if catalog.fuzzy and not options.use_fuzzy: + print 'catalog is marked as fuzzy, not compiling it' + sys.exit(0) print 'compiling catalog to %r' % options.output_file @@ -560,14 +573,21 @@ finally: outfile.close() else: - for po in available_pos: + for locale, po in available_pos: + loc_name = Locale.parse(locale).english_name infile = open(po, 'r') try: catalog = read_po(infile) finally: infile.close() + + if catalog.fuzzy: + print '%s catalog %r is marked as fuzzy, not compiling it' \ + % (loc_name, po) + continue - print 'compiling catalog to %r' % po.replace('.po', '.mo') + print 'compiling %s catalog to %r' % (loc_name, + po.replace('.po', '.mo')) outfile = open(po.replace('.po', '.mo'), 'w') try: diff --git a/babel/messages/pofile.py b/babel/messages/pofile.py --- a/babel/messages/pofile.py +++ b/babel/messages/pofile.py @@ -131,6 +131,8 @@ user_comments = [] auto_comments = [] in_msgid = in_msgstr = False + fuzzy_header = False + in_header = True def _add_message(): translations.sort() @@ -159,7 +161,12 @@ locations.append((filename, int(lineno))) elif line[1:].startswith(','): for flag in line[2:].lstrip().split(','): + if in_header: + if flag.strip() == 'fuzzy': + fuzzy_header = True flags.append(flag.strip()) + + elif line[1:].startswith('.'): # These are called auto-comments comment = line[2:].strip() @@ -176,9 +183,12 @@ messages.append(msg) elif line.startswith('msgid'): in_msgid = True + txt = line[5:].lstrip() + if txt == '""': + in_header = True if messages: _add_message() - messages.append(line[5:].lstrip()) + messages.append(txt) elif line.startswith('msgstr'): in_msgid = False in_msgstr = True @@ -190,12 +200,15 @@ translations.append([0, msg]) elif line.startswith('"'): if in_msgid: + in_header = False messages[-1] += u'\n' + line.rstrip() elif in_msgstr: translations[-1][1] += u'\n' + line.rstrip() if messages: _add_message() + + catalog.fuzzy = fuzzy_header return catalog WORD_SEP = re.compile('(' diff --git a/babel/messages/tests/pofile.py b/babel/messages/tests/pofile.py --- a/babel/messages/tests/pofile.py +++ b/babel/messages/tests/pofile.py @@ -35,6 +35,33 @@ 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 , 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 , 2007. +# +''') + catalog = pofile.read_po(buf) + self.assertEqual(1, len(list(catalog))) + self.assertEqual(False, list(catalog)[0].fuzzy) class WritePoTestCase(unittest.TestCase):