changeset 175:5d32098d8352 trunk

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.
author palgarvio
date Tue, 26 Jun 2007 16:46:56 +0000
parents bd256296086c
children 7a3073eab108
files babel/messages/catalog.py babel/messages/frontend.py babel/messages/pofile.py babel/messages/tests/pofile.py
diffstat 4 files changed, 92 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- 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
+        <Message 'foo' (Flags: 'fuzzy')>
         
         :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']
-        <Message u'foo'>
+        <Message u'foo' (Flags: '')>
         
         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']
-        <Message u'foo'>
+        <Message u'foo' (Flags: '')>
         
         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
-        [<Message 'head'>]
+        [<Message 'head' (Flags: '')>]
         
         :param template: the reference catalog, usually read from a POT file
         :param fuzzy_matching: whether to use fuzzy matching of message IDs
--- 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:
--- 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('('
--- 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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>, 2007.
+#
+''')
+        catalog = pofile.read_po(buf)
+        self.assertEqual(1, len(list(catalog)))
+        self.assertEqual(False, list(catalog)[0].fuzzy)
 
 
 class WritePoTestCase(unittest.TestCase):
Copyright (C) 2012-2017 Edgewall Software